diff --git a/.github/workflows/knip.yml b/.github/workflows/knip.yml new file mode 100644 index 000000000..ba8547b62 --- /dev/null +++ b/.github/workflows/knip.yml @@ -0,0 +1,22 @@ +name: knip + +on: + push: + branches: [main] + pull_request: {} + +jobs: + knip: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: oven-sh/setup-bun@v1 + - uses: pnpm/action-setup@v3 + with: + version: 9 + + - name: Install dependencies + run: pnpm i + + - name: Run knip + run: pnpm knip diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 47c5c3ad6..fcd21ee0c 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -9,7 +9,7 @@ jobs: prettier: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v1 - uses: pnpm/action-setup@v3 with: diff --git a/.github/workflows/test-contracts.yml b/.github/workflows/test-contracts.yml index c166e6547..90ac6d8c1 100644 --- a/.github/workflows/test-contracts.yml +++ b/.github/workflows/test-contracts.yml @@ -1,10 +1,6 @@ name: test-contracts -on: - push: - branches: - - main - pull_request: {} +on: [pull_request] jobs: setup-environment: @@ -39,7 +35,7 @@ jobs: steps: - name: Download Dojo release artifact run: | - curl -L -o dojo-linux-x86_64.tar.gz https://github.com/dojoengine/dojo/releases/download/v0.7.1/dojo_v0.7.1_linux_amd64.tar.gz + curl -L -o dojo-linux-x86_64.tar.gz https://github.com/dojoengine/dojo/releases/download/v1.0.0-alpha.3/dojo_v1.0.0-alpha.3_linux_amd64.tar.gz tar -xzf dojo-linux-x86_64.tar.gz sudo mv sozo /usr/local/bin/ - name: Checkout repository @@ -49,7 +45,7 @@ jobs: cd contracts && sozo build - name: Run Dojo Test for ${{ matrix.test }} run: | - cd contracts && sozo test -f ${{ matrix.test }} + cd contracts && sozo test -f ${{ matrix.test }} --print-resource-usage test-scarb-fmt: needs: [setup-environment] @@ -58,5 +54,5 @@ jobs: - uses: actions/checkout@v3 - uses: software-mansion/setup-scarb@v1 with: - scarb-version: "2.6.4" + scarb-version: "2.7.0-rc.4" - run: cd contracts && scarb fmt --check diff --git a/.knip.json b/.knip.json new file mode 100644 index 000000000..b7c8a6d66 --- /dev/null +++ b/.knip.json @@ -0,0 +1,20 @@ +{ + "ignore": [ + ".trunk/**", + "**/*.js", + "bot/**", + "**/vitest**", + "eternum-docs/package.json", + "eternum-docs/vocs.config.ts", + "sdk/packages/eternum/global.d.ts", + + "**/**__test__**/**", + "**/**__tests__**/**", + + "client/src/dojo/events/bankEventQueries.ts", + "client/src/hooks/store/useBankStore.tsx", + "client/src/ui/components/bank/BankEntityList.tsx", + "client/src/ui/components/bank/BankStats.tsx", + "config/bank/index.ts" + ] +} diff --git a/.tool-versions b/.tool-versions index 441b479d1..c0021b247 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1 @@ -scarb 2.6.4 \ No newline at end of file +scarb 2.7.0-rc.4 \ No newline at end of file diff --git a/client/.env.production b/client/.env.production index a4721f5fc..8197eb211 100644 --- a/client/.env.production +++ b/client/.env.production @@ -1,6 +1,6 @@ VITE_PUBLIC_MASTER_ADDRESS="0x7d7d5498052763f3358e429f8044f1f80ef0bbe790f7c7dcb98ef35d83ed6a8" VITE_PUBLIC_MASTER_PRIVATE_KEY="0x57556ee557df0571d59c05e767f65ec8c9378b7768f77ca1c1246f7c1c68cd1" -VITE_PUBLIC_WORLD_ADDRESS="0x161b08e252b353008665e85ab5dcb0044a61186eb14b999657d14c04c94c824" +VITE_PUBLIC_WORLD_ADDRESS="0x72bea8ba4bc0f95fb3313cc6b8b4228bbd38c329f53e972df7fe38fa055f357" VITE_PUBLIC_ACCOUNT_CLASS_HASH="0x05400e90f7e0ae78bd02c77cd75527280470e2fe19c54970dd79dc37a9d3645c" # VITE_NETWORK_FEE_TOKEN="0x51205c5e6ac3ad5691c28c0c5ffcdd62c70bddb63612f75a4bac9b2a85b9449" VITE_EVENT_KEY="0x1a2f334228cee715f1f0f54053bb6b5eac54fa336e0bc1aacf7516decb0471d" diff --git a/client/dojoConfig.ts b/client/dojoConfig.ts index bf15cc663..b915c4674 100644 --- a/client/dojoConfig.ts +++ b/client/dojoConfig.ts @@ -1,6 +1,6 @@ -import devManifest from "../contracts/manifests/dev/manifest.json"; -import productionManifest from "../contracts/manifests/prod/manifest.json"; import { createDojoConfig } from "@dojoengine/core"; +import devManifest from "../contracts/manifests/dev/deployment/manifest.json"; +import productionManifest from "../contracts/manifests/prod/deployment/manifest.json"; const { VITE_PUBLIC_NODE_URL, diff --git a/client/package.json b/client/package.json index bf9399513..fa73402cf 100644 --- a/client/package.json +++ b/client/package.json @@ -6,7 +6,7 @@ "dev": "vite --host 0.0.0.0", "build": "tsc && vite build", "preview": "vite preview", - "components": "npx @dojoengine/core ../contracts/manifests/dev/manifest.json src/dojo/contractComponents.ts http://localhost:5050 0x161b08e252b353008665e85ab5dcb0044a61186eb14b999657d14c04c94c824", + "components": "npx @dojoengine/core ../contracts/manifests/dev/deployment/manifest.json src/dojo/contractComponents.ts http://localhost:5050 0x72bea8ba4bc0f95fb3313cc6b8b4228bbd38c329f53e972df7fe38fa055f357", "test": "vitest run", "test:watch": "vitest", "test:ui": "vitest --ui", @@ -17,65 +17,49 @@ }, "dependencies": { "@bibliothecadao/eternum": "workspace:^", - "@dojoengine/core": "^0.7.9", - "@dojoengine/create-burner": "^0.7.3", - "@dojoengine/react": "^0.7.9", + "@dojoengine/core": "^v1.0.0-alpha.0", + "@dojoengine/create-burner": "^v1.0.0-alpha.0", + "@dojoengine/react": "^v1.0.0-alpha.0", "@dojoengine/recs": "^2.0.13", - "@dojoengine/state": "^0.7.9", - "@dojoengine/torii-client": "^0.7.9", - "@dojoengine/utils": "^0.7.9", - "@formkit/auto-animate": "^0.8.1", + "@dojoengine/state": "^v1.0.0-alpha.0", + "@dojoengine/torii-client": "^v1.0.0-alpha.0", + "@dojoengine/utils": "^v1.0.0-alpha.0", "@headlessui/react": "^1.7.18", - "@langchain/anthropic": "^0.1.14", "@latticexyz/utils": "^2.0.0-next.12", "@radix-ui/react-select": "^2.0.0", - "@react-spring/three": "^9.7.3", "@react-three/drei": "^9.101.0", "@react-three/fiber": "^8.16.1", "@react-three/postprocessing": "2.16.2", - "@reactour/tour": "^3.6.1", - "@testing-library/react-hooks": "^8.0.1", "@vercel/analytics": "^1.2.2", - "@web3mq/client": "^1.0.25", "buffer": "^6.0.3", "clsx": "^1.2.1", - "events": "^3.3.0", "framer-motion": "^11.0.24", "graphql": "16.6.0", "graphql-request": "6.0.0", - "graphql-tag": "^2.12.6", "graphql-ws": "^5.15.0", "gsap": "^3.12.5", "lodash": "^4.17.21", "lucide-react": "^0.365.0", "postprocessing": "^6.35.2", - "prop-types": "^15.8.1", "react": "^18.2.0", - "react-blurhash": "^0.3.0", "react-dom": "^18.2.0", "react-draggable": "^4.4.6", - "react-resizable": "^3.0.5", "react-toastify": "^10.0.5", "rxjs": "^7.8.1", "tailwind-merge": "^2.2.2", "three": "^0.163.0", - "three-csg": "^1.0.0", - "three-csg-ts": "^3.1.14", "three-stdlib": "^2.29.5", "use-sound": "^4.0.1", "wouter": "^2.12.1", - "ws": "^8.16.0", "zustand": "^4.5.2" }, "devDependencies": { "@svgr/rollup": "^8.1.0", "@tailwindcss/typography": "^0.5.13", - "@testing-library/react": "^16.0.0", "@types/lodash": "^4.14.202", "@types/node": "^20.11.10", "@types/react": "^18.2.74", "@types/react-dom": "^18.2.21", - "@types/react-resizable": "^3.0.7", "@types/three": "^0.163.0", "@typescript-eslint/eslint-plugin": "^7.5.0", "@vitejs/plugin-react": "^4.2.1", diff --git a/client/src/assets/icons/orders/index.tsx b/client/src/assets/icons/orders/index.tsx deleted file mode 100644 index b19f87b9f..000000000 --- a/client/src/assets/icons/orders/index.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import Anger from "./anger.svg"; -import Brilliance from "./brilliance.svg"; -import Detection from "./detection.svg"; -import Enlightenment from "./enlightenment.svg"; -import Fox from "./fox.svg"; -import Fury from "./fury.svg"; -import Giants from "./giants.svg"; -import Perfection from "./perfection.svg"; -import Power from "./power.svg"; -import Protection from "./protection.svg"; -import Rage from "./rage.svg"; -import Reflection from "./reflection.svg"; -import Skill from "./skill.svg"; -import Titans from "./titans.svg"; -import Twins from "./twins.svg"; -import Vitriol from "./vitriol.svg"; - -export { - Anger, - Brilliance, - Detection, - Enlightenment, - Fox, - Fury, - Giants, - Perfection, - Power, - Protection, - Rage, - Reflection, - Skill, - Titans, - Twins, - Vitriol, -}; diff --git a/client/src/dojo/contractComponents.ts b/client/src/dojo/contractComponents.ts index 5281f151e..54c8ff2fc 100644 --- a/client/src/dojo/contractComponents.ts +++ b/client/src/dojo/contractComponents.ts @@ -2,158 +2,47 @@ import { defineComponent, Type as RecsType, World } from "@dojoengine/recs"; -export type ContractComponents = ReturnType; - export function defineContractComponents(world: World) { return { - Structure: (() => { - return defineComponent( - world, - { - entity_id: RecsType.BigInt, - category: RecsType.String, - }, - { - metadata: { - name: "Structure", - types: ["u128", "enum"], - customTypes: [], - }, - }, - ); - })(), - Progress: (() => { - return defineComponent( - world, - { - hyperstructure_entity_id: RecsType.BigInt, - resource_type: RecsType.Number, - amount: RecsType.Number, - }, - { - metadata: { - name: "Progress", - types: ["u128", "u8", "u128"], - customTypes: [], - }, - }, - ); - })(), - Contribution: (() => { - return defineComponent( - world, - { - hyperstructure_entity_id: RecsType.BigInt, - player_address: RecsType.BigInt, - resource_type: RecsType.BigInt, - amount: RecsType.BigInt, - }, - { - metadata: { - name: "Contribution", - types: ["u128", "u128", "u8", "u128"], - customTypes: [], - }, - }, - ); - })(), - Production: (() => { - return defineComponent( - world, - { - entity_id: RecsType.BigInt, - resource_type: RecsType.Number, - building_count: RecsType.BigInt, - production_rate: RecsType.BigInt, - consumption_rate: RecsType.BigInt, - last_updated_tick: RecsType.BigInt, - input_finish_tick: RecsType.BigInt, - }, - { - metadata: { - name: "Production", - types: ["u128", "u8", "u128", "u128", "u128", "u128", "u64", "u64"], - customTypes: [], - }, - }, - ); - })(), - ProductionInput: (() => { - return defineComponent( - world, - { - output_resource_type: RecsType.Number, - index: RecsType.Number, - input_resource_type: RecsType.Number, - input_resource_amount: RecsType.BigInt, - }, - { - metadata: { - name: "ProductionInput", - types: ["u8", "u8", "u8", "u128"], - customTypes: [], - }, - }, - ); - })(), - ProductionOutput: (() => { + AddressName: (() => { return defineComponent( world, - { input_resource_type: RecsType.Number, index: RecsType.Number, output_resource_type: RecsType.Number }, + { address: RecsType.BigInt, name: RecsType.BigInt }, { metadata: { - name: "ProductionOutput", - types: ["u8", "u8", "u8"], + name: "eternum-AddressName", + types: ["felt252", "felt252"], customTypes: [], }, }, ); })(), - Liquidity: (() => { + Army: (() => { return defineComponent( world, { - bank_entity_id: RecsType.BigInt, - player: RecsType.BigInt, - resource_type: RecsType.BigInt, - shares: { mag: RecsType.BigInt, sign: RecsType.Boolean }, - }, - { - metadata: { - name: "Liquidity", - types: ["u128", "u128", "u8", "u128", "bool"], - customTypes: [], - }, + entity_id: RecsType.Number, + troops: { knight_count: RecsType.BigInt, paladin_count: RecsType.BigInt, crossbowman_count: RecsType.BigInt }, + battle_id: RecsType.Number, + battle_side: RecsType.String, }, - ); - })(), - BuildingQuantityv2: (() => { - return defineComponent( - world, - { entity_id: RecsType.BigInt, category: RecsType.Number, value: RecsType.Number }, { metadata: { - name: "BuildingQuantityv2", - types: ["u128", "enum", "u8"], - customTypes: ["BuildingCategory"], + name: "eternum-Army", + types: ["u32", "u64", "u64", "u64", "u32", "enum"], + customTypes: ["Troops", "BattleSide"], }, }, ); })(), - Market: (() => { + ArrivalTime: (() => { return defineComponent( world, - { - bank_entity_id: RecsType.BigInt, - resource_type: RecsType.BigInt, - lords_amount: RecsType.BigInt, - resource_amount: RecsType.BigInt, - total_shares: { mag: RecsType.BigInt, sign: RecsType.Boolean }, - }, + { entity_id: RecsType.Number, arrives_at: RecsType.BigInt }, { metadata: { - name: "Market", - types: ["u128", "u8", "u128", "u128"], + name: "eternum-ArrivalTime", + types: ["u32", "u64"], customTypes: [], }, }, @@ -163,34 +52,34 @@ export function defineContractComponents(world: World) { return defineComponent( world, { - entity_id: RecsType.BigInt, + entity_id: RecsType.Number, owner_fee_num: RecsType.BigInt, owner_fee_denom: RecsType.BigInt, exists: RecsType.Boolean, }, { metadata: { - name: "Bank", - types: ["u128", "u128", "u128", "bool"], + name: "eternum-Bank", + types: ["u32", "u128", "u128", "bool"], customTypes: [], }, }, ); })(), - Army: (() => { + BankConfig: (() => { return defineComponent( world, { - entity_id: RecsType.BigInt, - troops: { knight_count: RecsType.BigInt, paladin_count: RecsType.BigInt, crossbowman_count: RecsType.BigInt }, - battle_id: RecsType.BigInt, - battle_side: RecsType.String, + config_id: RecsType.Number, + lords_cost: RecsType.BigInt, + lp_fee_num: RecsType.BigInt, + lp_fee_denom: RecsType.BigInt, }, { metadata: { - name: "Army", - types: ["u128", "u32", "u32", "u32", "u128", "enum"], - customTypes: ["Troops", "BattleSide"], + name: "eternum-BankConfig", + types: ["u32", "u128", "u128", "u128"], + customTypes: [], }, }, ); @@ -199,15 +88,15 @@ export function defineContractComponents(world: World) { return defineComponent( world, { - entity_id: RecsType.BigInt, + entity_id: RecsType.Number, attack_army: { troops: { knight_count: RecsType.BigInt, paladin_count: RecsType.BigInt, crossbowman_count: RecsType.BigInt, }, - battle_id: RecsType.BigInt, - battle_side: RecsType.Number, + battle_id: RecsType.Number, + battle_side: RecsType.String, }, attack_army_lifetime: { troops: { @@ -215,8 +104,8 @@ export function defineContractComponents(world: World) { paladin_count: RecsType.BigInt, crossbowman_count: RecsType.BigInt, }, - battle_id: RecsType.BigInt, - battle_side: RecsType.Number, + battle_id: RecsType.Number, + battle_side: RecsType.String, }, defence_army: { troops: { @@ -224,8 +113,8 @@ export function defineContractComponents(world: World) { paladin_count: RecsType.BigInt, crossbowman_count: RecsType.BigInt, }, - battle_id: RecsType.BigInt, - battle_side: RecsType.Number, + battle_id: RecsType.Number, + battle_side: RecsType.String, }, defence_army_lifetime: { troops: { @@ -233,11 +122,11 @@ export function defineContractComponents(world: World) { paladin_count: RecsType.BigInt, crossbowman_count: RecsType.BigInt, }, - battle_id: RecsType.BigInt, - battle_side: RecsType.Number, + battle_id: RecsType.Number, + battle_side: RecsType.String, }, - attackers_resources_escrow_id: RecsType.BigInt, - defenders_resources_escrow_id: RecsType.BigInt, + attackers_resources_escrow_id: RecsType.Number, + defenders_resources_escrow_id: RecsType.Number, attack_army_health: { current: RecsType.BigInt, lifetime: RecsType.BigInt }, defence_army_health: { current: RecsType.BigInt, lifetime: RecsType.BigInt }, attack_delta: RecsType.BigInt, @@ -247,31 +136,31 @@ export function defineContractComponents(world: World) { }, { metadata: { - name: "Battle", + name: "eternum-Battle", types: [ - "u128", + "u32", "u64", "u64", "u64", - "u128", + "u32", "enum", "u64", "u64", "u64", - "u128", + "u32", "enum", "u64", "u64", "u64", - "u128", + "u32", "enum", "u64", "u64", "u64", - "u128", + "u32", "enum", - "u128", - "u128", + "u32", + "u32", "u128", "u128", "u128", @@ -301,315 +190,414 @@ export function defineContractComponents(world: World) { }, ); })(), - Health: (() => { + BattleConfig: (() => { return defineComponent( world, - { entity_id: RecsType.BigInt, current: RecsType.BigInt, lifetime: RecsType.BigInt }, + { entity_id: RecsType.Number, max_tick_duration: RecsType.BigInt }, { metadata: { - name: "Health", - types: ["u128", "u128", "u128"], + name: "eternum-BattleConfig", + types: ["u32", "u64"], customTypes: [], }, }, ); })(), - Capacity: (() => { + Building: (() => { return defineComponent( world, - { entity_id: RecsType.BigInt, weight_gram: RecsType.BigInt }, + { + outer_col: RecsType.Number, + outer_row: RecsType.Number, + inner_col: RecsType.Number, + inner_row: RecsType.Number, + category: RecsType.String, + produced_resource_type: RecsType.Number, + bonus_percent: RecsType.Number, + entity_id: RecsType.Number, + outer_entity_id: RecsType.Number, + }, { metadata: { - name: "Capacity", - types: ["u128", "u128"], - customTypes: [], + name: "eternum-Building", + types: ["u32", "u32", "u32", "u32", "enum", "u8", "u32", "u32", "u32"], + customTypes: ["BuildingCategory"], }, }, ); })(), - Building: (() => { + BuildingCategoryPopConfig: (() => { return defineComponent( world, { - outer_col: RecsType.BigInt, - outer_row: RecsType.BigInt, - inner_col: RecsType.BigInt, - inner_row: RecsType.BigInt, + config_id: RecsType.Number, + building_category: RecsType.String, + population: RecsType.Number, + capacity: RecsType.Number, + }, + { + metadata: { + name: "eternum-BuildingCategoryPopConfig", + types: ["u32", "enum", "u32", "u32"], + customTypes: ["BuildingCategory"], + }, + }, + ); + })(), + BuildingConfig: (() => { + return defineComponent( + world, + { + config_id: RecsType.Number, category: RecsType.String, - produced_resource_type: RecsType.Number, - bonus_percent: RecsType.BigInt, - entity_id: RecsType.BigInt, - outer_entity_id: RecsType.BigInt, + resource_type: RecsType.Number, + resource_cost_id: RecsType.Number, + resource_cost_count: RecsType.Number, }, { metadata: { - name: "Building", - types: ["u128", "u128", "u128", "u128", "enum", "u8", "u128", "u128"], + name: "eternum-BuildingConfig", + types: ["u32", "enum", "u8", "u32", "u32"], customTypes: ["BuildingCategory"], }, }, ); })(), + BuildingQuantityv2: (() => { + return defineComponent( + world, + { entity_id: RecsType.Number, category: RecsType.String, value: RecsType.Number }, + { + metadata: { + name: "eternum-BuildingQuantityv2", + types: ["u32", "enum", "u8"], + customTypes: ["BuildingCategory"], + }, + }, + ); + })(), + Capacity: (() => { + return defineComponent( + world, + { entity_id: RecsType.Number, weight_gram: RecsType.BigInt }, + { + metadata: { + name: "eternum-Capacity", + types: ["u32", "u128"], + customTypes: [], + }, + }, + ); + })(), CapacityConfig: (() => { return defineComponent( world, { - config_id: RecsType.BigInt, - carry_capacity_config_id: RecsType.BigInt, - entity_type: RecsType.BigInt, + config_id: RecsType.Number, + carry_capacity_config_id: RecsType.Number, + entity_type: RecsType.Number, weight_gram: RecsType.BigInt, }, { metadata: { - name: "CapacityConfig", - types: ["u128", "u128", "u128", "u128"], + name: "eternum-CapacityConfig", + types: ["u32", "u32", "u32", "u128"], customTypes: [], }, }, ); })(), - LevelingConfig: (() => { + Contribution: (() => { return defineComponent( world, { - config_id: RecsType.BigInt, - decay_interval: RecsType.Number, - max_level: RecsType.Number, - decay_scaled: RecsType.BigInt, - cost_percentage_scaled: RecsType.BigInt, - base_multiplier: RecsType.BigInt, - wheat_base_amount: RecsType.BigInt, - fish_base_amount: RecsType.BigInt, - resource_1_cost_id: RecsType.BigInt, - resource_1_cost_count: RecsType.Number, - resource_2_cost_id: RecsType.BigInt, - resource_2_cost_count: RecsType.Number, - resource_3_cost_id: RecsType.BigInt, - resource_3_cost_count: RecsType.Number, + hyperstructure_entity_id: RecsType.Number, + player_address: RecsType.BigInt, + resource_type: RecsType.Number, + amount: RecsType.BigInt, }, { metadata: { - name: "LevelingConfig", - types: [ - "u128", - "u64", - "u64", - "u128", - "u128", - "u128", - "u128", - "u128", - "u128", - "u32", - "u128", - "u32", - "u128", - "u32", - ], + name: "eternum-Contribution", + types: ["u32", "contractaddress", "u8", "u128"], customTypes: [], }, }, ); })(), - RoadConfig: (() => { + DetachedResource: (() => { return defineComponent( world, { - config_id: RecsType.BigInt, - fee_resource_type: RecsType.Number, - fee_amount: RecsType.BigInt, - speed_up_by: RecsType.Number, + entity_id: RecsType.Number, + index: RecsType.Number, + resource_type: RecsType.Number, + resource_amount: RecsType.BigInt, }, { metadata: { - name: "RoadConfig", - types: ["u128", "u8", "u128", "u64"], + name: "eternum-DetachedResource", + types: ["u32", "u32", "u8", "u128"], customTypes: [], }, }, ); })(), - HasClaimedStartingResources: (() => { + EntityMetadata: (() => { return defineComponent( world, - { entity_id: RecsType.BigInt, config_id: RecsType.Number, claimed: RecsType.Boolean }, + { entity_id: RecsType.Number, entity_type: RecsType.Number }, { metadata: { - name: "HasClaimedStartingResources", - types: ["u128", "u32", "bool"], + name: "eternum-EntityMetadata", + types: ["u32", "u32"], customTypes: [], }, }, ); })(), - SoldierConfig: (() => { + EntityName: (() => { return defineComponent( world, + { entity_id: RecsType.Number, name: RecsType.BigInt }, { - config_id: RecsType.BigInt, - resource_cost_id: RecsType.BigInt, - resource_cost_count: RecsType.Number, - wheat_burn_per_soldier: RecsType.BigInt, - fish_burn_per_soldier: RecsType.BigInt, + metadata: { + name: "eternum-EntityName", + types: ["u32", "felt252"], + customTypes: [], + }, }, + ); + })(), + EntityOwner: (() => { + return defineComponent( + world, + { entity_id: RecsType.Number, entity_owner_id: RecsType.Number }, { metadata: { - name: "SoldierConfig", - types: ["u128", "u128", "u32", "u128", "u128"], + name: "eternum-EntityOwner", + types: ["u32", "u32"], customTypes: [], }, }, ); })(), - SpeedConfig: (() => { + ForeignKey: (() => { return defineComponent( world, + { foreign_key: RecsType.BigInt, entity_id: RecsType.Number }, { - config_id: RecsType.BigInt, - speed_config_id: RecsType.BigInt, - entity_type: RecsType.BigInt, - sec_per_km: RecsType.Number, + metadata: { + name: "eternum-ForeignKey", + types: ["felt252", "u32"], + customTypes: [], + }, }, + ); + })(), + Guild: (() => { + return defineComponent( + world, + { entity_id: RecsType.Number, is_public: RecsType.Boolean, member_count: RecsType.Number }, { metadata: { - name: "SpeedConfig", - types: ["u128", "u128", "u128", "u16"], + name: "eternum-Guild", + types: ["u32", "bool", "u16"], customTypes: [], }, }, ); })(), - TravelConfig: (() => { + GuildMember: (() => { return defineComponent( world, - { config_id: RecsType.BigInt, free_transport_per_city: RecsType.BigInt }, + { address: RecsType.BigInt, guild_entity_id: RecsType.Number }, { metadata: { - name: "TravelConfig", - types: ["u128", "u128"], + name: "eternum-GuildMember", + types: ["contractaddress", "u32"], customTypes: [], }, }, ); })(), - WeightConfig: (() => { + GuildWhitelist: (() => { return defineComponent( world, + { address: RecsType.BigInt, guild_entity_id: RecsType.Number, is_whitelisted: RecsType.Boolean }, { - config_id: RecsType.BigInt, - weight_config_id: RecsType.BigInt, - entity_type: RecsType.BigInt, - weight_gram: RecsType.BigInt, + metadata: { + name: "eternum-GuildWhitelist", + types: ["contractaddress", "u32", "bool"], + customTypes: [], + }, }, + ); + })(), + HasClaimedStartingResources: (() => { + return defineComponent( + world, + { entity_id: RecsType.Number, config_id: RecsType.Number, claimed: RecsType.Boolean }, { metadata: { - name: "WeightConfig", - types: ["u128", "u128", "u128", "u128"], + name: "eternum-HasClaimedStartingResources", + types: ["u32", "u32", "bool"], customTypes: [], }, }, ); })(), - Protectee: (() => { + Health: (() => { return defineComponent( world, - { army_id: RecsType.BigInt, protectee_id: RecsType.BigInt }, + { entity_id: RecsType.Number, current: RecsType.BigInt, lifetime: RecsType.BigInt }, { metadata: { - name: "Protectee", - types: ["u128", "u128"], + name: "eternum-Health", + types: ["u32", "u128", "u128"], customTypes: [], }, }, ); })(), - Protector: (() => { + HyperstructureResourceConfig: (() => { return defineComponent( world, - { entity_id: RecsType.BigInt, army_id: RecsType.BigInt }, + { config_id: RecsType.Number, resource_type: RecsType.Number, amount_for_completion: RecsType.BigInt }, { metadata: { - name: "Protector", - types: ["u128", "u128"], + name: "eternum-HyperstructureResourceConfig", + types: ["u32", "u8", "u128"], customTypes: [], }, }, ); })(), - WorldConfig: (() => { + Level: (() => { return defineComponent( world, - { config_id: RecsType.BigInt, admin_address: RecsType.BigInt, realm_l2_contract: RecsType.BigInt }, + { entity_id: RecsType.Number, level: RecsType.BigInt, valid_until: RecsType.BigInt }, { metadata: { - name: "WorldConfig", - types: ["u128", "contractaddress", "contractaddress"], + name: "eternum-Level", + types: ["u32", "u64", "u64"], customTypes: [], }, }, ); })(), - EntityName: (() => { + LevelingConfig: (() => { return defineComponent( world, - { entity_id: RecsType.BigInt, name: RecsType.BigInt }, + { + config_id: RecsType.Number, + decay_interval: RecsType.BigInt, + max_level: RecsType.BigInt, + decay_scaled: RecsType.BigInt, + cost_percentage_scaled: RecsType.BigInt, + base_multiplier: RecsType.BigInt, + wheat_base_amount: RecsType.BigInt, + fish_base_amount: RecsType.BigInt, + resource_1_cost_id: RecsType.Number, + resource_1_cost_count: RecsType.Number, + resource_2_cost_id: RecsType.Number, + resource_2_cost_count: RecsType.Number, + resource_3_cost_id: RecsType.Number, + resource_3_cost_count: RecsType.Number, + }, { metadata: { - name: "EntityName", - types: ["u128", "felt252"], + name: "eternum-LevelingConfig", + types: [ + "u32", + "u64", + "u64", + "u128", + "u128", + "u128", + "u128", + "u128", + "u32", + "u32", + "u32", + "u32", + "u32", + "u32", + ], customTypes: [], }, }, ); })(), - Level: (() => { + Liquidity: (() => { return defineComponent( world, - { entity_id: RecsType.BigInt, level: RecsType.Number, valid_until: RecsType.Number }, + { + bank_entity_id: RecsType.Number, + player: RecsType.BigInt, + resource_type: RecsType.Number, + shares: { mag: RecsType.BigInt, sign: RecsType.Boolean }, + }, { metadata: { - name: "Level", - types: ["u128", "u64", "u64"], - customTypes: [], + name: "eternum-Liquidity", + types: ["u32", "contractaddress", "u8", "u128", "bool"], + customTypes: ["Fixed"], }, }, ); })(), - EntityMetadata: (() => { + MapExploreConfig: (() => { return defineComponent( world, - { entity_id: RecsType.BigInt, entity_type: RecsType.BigInt }, + { + config_id: RecsType.Number, + wheat_burn_amount: RecsType.BigInt, + fish_burn_amount: RecsType.BigInt, + reward_resource_amount: RecsType.BigInt, + shards_mines_fail_probability: RecsType.BigInt, + }, { metadata: { - name: "EntityMetadata", - types: ["u128", "u128"], + name: "eternum-MapExploreConfig", + types: ["u32", "u128", "u128", "u128", "u128"], customTypes: [], }, }, ); })(), - ForeignKey: (() => { + Market: (() => { return defineComponent( world, - { foreign_key: RecsType.BigInt, entity_id: RecsType.BigInt }, + { + bank_entity_id: RecsType.Number, + resource_type: RecsType.Number, + lords_amount: RecsType.BigInt, + resource_amount: RecsType.BigInt, + total_shares: { mag: RecsType.BigInt, sign: RecsType.Boolean }, + }, { metadata: { - name: "ForeignKey", - types: ["felt252", "u128"], - customTypes: [], + name: "eternum-Market", + types: ["u32", "u8", "u128", "u128", "u128", "bool"], + customTypes: ["Fixed"], }, }, ); })(), - ArrivalTime: (() => { + MercenariesConfig: (() => { return defineComponent( world, - { entity_id: RecsType.BigInt, arrives_at: RecsType.Number }, + { + config_id: RecsType.Number, + troops: { knight_count: RecsType.BigInt, paladin_count: RecsType.BigInt, crossbowman_count: RecsType.BigInt }, + rewards: RecsType.StringArray, + }, { metadata: { - name: "ArrivalTime", - types: ["u128", "u64"], - customTypes: [], + name: "eternum-MercenariesConfig", + types: ["u32", "u64", "u64", "u64"], + customTypes: ["Troops"], }, }, ); @@ -618,7 +606,7 @@ export function defineContractComponents(world: World) { return defineComponent( world, { - entity_id: RecsType.BigInt, + entity_id: RecsType.Number, sec_per_km: RecsType.Number, blocked: RecsType.Boolean, round_trip: RecsType.Boolean, @@ -629,34 +617,34 @@ export function defineContractComponents(world: World) { }, { metadata: { - name: "Movable", - types: ["u128", "u16", "bool", "bool", "u32", "u32"], + name: "eternum-Movable", + types: ["u32", "u16", "bool", "bool", "u32", "u32", "u32", "u32"], customTypes: [], }, }, ); })(), - AddressName: (() => { + Orders: (() => { return defineComponent( world, - { address: RecsType.BigInt, name: RecsType.BigInt }, + { order_id: RecsType.Number, hyperstructure_count: RecsType.Number }, { metadata: { - name: "AddressName", - types: ["felt252", "felt252"], + name: "eternum-Orders", + types: ["u32", "u32"], customTypes: [], }, }, ); })(), - EntityOwner: (() => { + OwnedResourcesTracker: (() => { return defineComponent( world, - { entity_id: RecsType.BigInt, entity_owner_id: RecsType.BigInt }, + { entity_id: RecsType.Number, resource_types: RecsType.BigInt }, { metadata: { - name: "EntityOwner", - types: ["u128", "u128"], + name: "eternum-OwnedResourcesTracker", + types: ["u32", "u256"], customTypes: [], }, }, @@ -665,11 +653,37 @@ export function defineContractComponents(world: World) { Owner: (() => { return defineComponent( world, - { entity_id: RecsType.BigInt, address: RecsType.BigInt }, + { entity_id: RecsType.Number, address: RecsType.BigInt }, { metadata: { - name: "Owner", - types: ["u128", "contractaddress"], + name: "eternum-Owner", + types: ["u32", "contractaddress"], + customTypes: [], + }, + }, + ); + })(), + Population: (() => { + return defineComponent( + world, + { entity_id: RecsType.Number, population: RecsType.Number, capacity: RecsType.Number }, + { + metadata: { + name: "eternum-Population", + types: ["u32", "u32", "u32"], + customTypes: [], + }, + }, + ); + })(), + PopulationConfig: (() => { + return defineComponent( + world, + { config_id: RecsType.Number, base_population: RecsType.Number }, + { + metadata: { + name: "eternum-PopulationConfig", + types: ["u32", "u32"], customTypes: [], }, }, @@ -678,50 +692,146 @@ export function defineContractComponents(world: World) { Position: (() => { return defineComponent( world, - { entity_id: RecsType.BigInt, x: RecsType.Number, y: RecsType.Number }, + { entity_id: RecsType.Number, x: RecsType.Number, y: RecsType.Number }, { metadata: { - name: "Position", - types: ["u128", "u32", "u32"], + name: "eternum-Position", + types: ["u32", "u32", "u32"], customTypes: [], }, }, ); })(), - Quantity: (() => { + Production: (() => { return defineComponent( world, - { entity_id: RecsType.BigInt, value: RecsType.BigInt }, + { + entity_id: RecsType.Number, + resource_type: RecsType.Number, + building_count: RecsType.Number, + production_rate: RecsType.BigInt, + consumption_rate: RecsType.BigInt, + last_updated_tick: RecsType.BigInt, + input_finish_tick: RecsType.BigInt, + }, { metadata: { - name: "Quantity", - types: ["u128", "u128"], + name: "eternum-Production", + types: ["u32", "u8", "u8", "u128", "u128", "u64", "u64"], customTypes: [], }, }, ); })(), - QuantityTracker: (() => { + ProductionConfig: (() => { return defineComponent( world, - { entity_id: RecsType.BigInt, count: RecsType.BigInt }, + { + resource_type: RecsType.Number, + amount: RecsType.BigInt, + input_count: RecsType.BigInt, + output_count: RecsType.BigInt, + }, { metadata: { - name: "QuantityTracker", - types: ["felt252", "u128"], + name: "eternum-ProductionConfig", + types: ["u8", "u128", "u128", "u128"], customTypes: [], }, }, ); })(), - Population: (() => { + ProductionInput: (() => { + return defineComponent( + world, + { + output_resource_type: RecsType.Number, + index: RecsType.Number, + input_resource_type: RecsType.Number, + input_resource_amount: RecsType.BigInt, + }, + { + metadata: { + name: "eternum-ProductionInput", + types: ["u8", "u8", "u8", "u128"], + customTypes: [], + }, + }, + ); + })(), + ProductionOutput: (() => { + return defineComponent( + world, + { input_resource_type: RecsType.Number, index: RecsType.Number, output_resource_type: RecsType.Number }, + { + metadata: { + name: "eternum-ProductionOutput", + types: ["u8", "u8", "u8"], + customTypes: [], + }, + }, + ); + })(), + Progress: (() => { + return defineComponent( + world, + { hyperstructure_entity_id: RecsType.Number, resource_type: RecsType.Number, amount: RecsType.BigInt }, + { + metadata: { + name: "eternum-Progress", + types: ["u32", "u8", "u128"], + customTypes: [], + }, + }, + ); + })(), + Protectee: (() => { return defineComponent( world, - { entity_id: RecsType.BigInt, population: RecsType.Number, capacity: RecsType.Number }, + { army_id: RecsType.Number, protectee_id: RecsType.Number }, { metadata: { - name: "Population", - types: ["u128", "u32", "u32"], + name: "eternum-Protectee", + types: ["u32", "u32"], + customTypes: [], + }, + }, + ); + })(), + Protector: (() => { + return defineComponent( + world, + { entity_id: RecsType.Number, army_id: RecsType.Number }, + { + metadata: { + name: "eternum-Protector", + types: ["u32", "u32"], + customTypes: [], + }, + }, + ); + })(), + Quantity: (() => { + return defineComponent( + world, + { entity_id: RecsType.Number, value: RecsType.BigInt }, + { + metadata: { + name: "eternum-Quantity", + types: ["u32", "u128"], + customTypes: [], + }, + }, + ); + })(), + QuantityTracker: (() => { + return defineComponent( + world, + { entity_id: RecsType.BigInt, count: RecsType.BigInt }, + { + metadata: { + name: "eternum-QuantityTracker", + types: ["felt252", "u128"], customTypes: [], }, }, @@ -731,8 +841,8 @@ export function defineContractComponents(world: World) { return defineComponent( world, { - entity_id: RecsType.BigInt, - realm_id: RecsType.BigInt, + entity_id: RecsType.Number, + realm_id: RecsType.Number, resource_types_packed: RecsType.BigInt, resource_types_count: RecsType.Number, cities: RecsType.Number, @@ -744,33 +854,21 @@ export function defineContractComponents(world: World) { }, { metadata: { - name: "Realm", - types: ["u128", "u128", "u128", "u8", "u8", "u8", "u8", "u8", "u8", "u8"], + name: "eternum-Realm", + types: ["u32", "u32", "u128", "u8", "u8", "u8", "u8", "u8", "u8", "u8"], customTypes: [], }, }, ); })(), - OwnedResourcesTracker: (() => { - return defineComponent( - world, - { entity_id: RecsType.BigInt, resource_types: RecsType.BigInt }, - { metadata: { name: "OwnedResourcesTracker", types: ["u128", "felt252"], customTypes: [] } }, - ); - })(), - DetachedResource: (() => { + RealmFreeMintConfig: (() => { return defineComponent( world, - { - entity_id: RecsType.BigInt, - index: RecsType.Number, - resource_type: RecsType.Number, - resource_amount: RecsType.BigInt, - }, + { config_id: RecsType.Number, detached_resource_id: RecsType.Number, detached_resource_count: RecsType.Number }, { metadata: { - name: "DetachedResource", - types: ["u128", "u32", "u8", "u128"], + name: "eternum-RealmFreeMintConfig", + types: ["u32", "u32", "u32"], customTypes: [], }, }, @@ -779,11 +877,11 @@ export function defineContractComponents(world: World) { Resource: (() => { return defineComponent( world, - { entity_id: RecsType.BigInt, resource_type: RecsType.Number, balance: RecsType.BigInt }, + { entity_id: RecsType.Number, resource_type: RecsType.Number, balance: RecsType.BigInt }, { metadata: { - name: "Resource", - types: ["u128", "u8", "u128"], + name: "eternum-Resource", + types: ["u32", "u8", "u128"], customTypes: [], }, }, @@ -793,15 +891,15 @@ export function defineContractComponents(world: World) { return defineComponent( world, { - owner_entity_id: RecsType.BigInt, - approved_entity_id: RecsType.BigInt, + owner_entity_id: RecsType.Number, + approved_entity_id: RecsType.Number, resource_type: RecsType.Number, amount: RecsType.BigInt, }, { metadata: { - name: "ResourceAllowance", - types: ["u128", "u128", "u8", "u128"], + name: "eternum-ResourceAllowance", + types: ["u32", "u32", "u8", "u128"], customTypes: [], }, }, @@ -810,11 +908,11 @@ export function defineContractComponents(world: World) { ResourceCost: (() => { return defineComponent( world, - { entity_id: RecsType.BigInt, index: RecsType.Number, resource_type: RecsType.Number, amount: RecsType.BigInt }, + { entity_id: RecsType.Number, index: RecsType.Number, resource_type: RecsType.Number, amount: RecsType.BigInt }, { metadata: { - name: "ResourceCost", - types: ["u128", "u32", "u8", "u128"], + name: "eternum-ResourceCost", + types: ["u32", "u32", "u8", "u128"], customTypes: [], }, }, @@ -823,11 +921,11 @@ export function defineContractComponents(world: World) { ResourceTransferLock: (() => { return defineComponent( world, - { entity_id: RecsType.BigInt, release_at: RecsType.BigInt }, + { entity_id: RecsType.Number, release_at: RecsType.BigInt }, { metadata: { - name: "ResourceTransferLock", - types: ["u128", "u64"], + name: "eternum-ResourceTransferLock", + types: ["u32", "u64"], customTypes: [], }, }, @@ -845,193 +943,233 @@ export function defineContractComponents(world: World) { }, { metadata: { - name: "Road", + name: "eternum-Road", types: ["u32", "u32", "u32", "u32", "u32"], customTypes: [], }, }, ); })(), - Status: (() => { + RoadConfig: (() => { return defineComponent( world, - { trade_id: RecsType.BigInt, value: RecsType.BigInt }, + { + config_id: RecsType.Number, + resource_cost_id: RecsType.Number, + resource_cost_count: RecsType.Number, + speed_up_by: RecsType.BigInt, + }, { metadata: { - name: "Status", - types: ["u128", "u128"], + name: "eternum-RoadConfig", + types: ["u32", "u32", "u32", "u64"], customTypes: [], }, }, ); })(), - Trade: (() => { + SpeedConfig: (() => { return defineComponent( world, { - trade_id: RecsType.BigInt, - maker_id: RecsType.BigInt, - maker_gives_resources_id: RecsType.BigInt, - maker_gives_resources_hash: RecsType.BigInt, - maker_gives_resources_weight: RecsType.BigInt, - taker_id: RecsType.BigInt, - taker_gives_resources_id: RecsType.BigInt, - taker_gives_resources_hash: RecsType.BigInt, - taker_gives_resources_weight: RecsType.BigInt, - expires_at: RecsType.Number, + config_id: RecsType.Number, + speed_config_id: RecsType.Number, + entity_type: RecsType.Number, + sec_per_km: RecsType.Number, }, { metadata: { - name: "Trade", - types: ["u128", "u128", "u128", "felt252", "u128", "u128", "u128", "felt252", "u128", "u64"], + name: "eternum-SpeedConfig", + types: ["u32", "u32", "u32", "u16"], customTypes: [], }, }, ); })(), - Weight: (() => { + Stamina: (() => { return defineComponent( world, - { entity_id: RecsType.BigInt, value: RecsType.BigInt }, + { entity_id: RecsType.Number, amount: RecsType.Number, last_refill_tick: RecsType.BigInt }, { metadata: { - name: "Weight", - types: ["u128", "u128"], + name: "eternum-Stamina", + types: ["u32", "u16", "u64"], customTypes: [], }, }, ); })(), - Orders: (() => { + StaminaConfig: (() => { return defineComponent( world, - { order_id: RecsType.BigInt, hyperstructure_count: RecsType.BigInt }, + { config_id: RecsType.Number, unit_type: RecsType.Number, max_stamina: RecsType.Number }, { metadata: { - name: "Orders", - types: ["u128", "u128"], + name: "eternum-StaminaConfig", + types: ["u32", "u8", "u16"], customTypes: [], }, }, ); })(), - Tile: (() => { + Status: (() => { return defineComponent( world, + { trade_id: RecsType.Number, value: RecsType.BigInt }, { - _col: RecsType.BigInt, - _row: RecsType.BigInt, - col: RecsType.BigInt, - row: RecsType.BigInt, - explored_by_id: RecsType.BigInt, - explored_at: RecsType.Number, - biome: RecsType.Number, + metadata: { + name: "eternum-Status", + types: ["u32", "u128"], + customTypes: [], + }, }, + ); + })(), + Structure: (() => { + return defineComponent( + world, + { entity_id: RecsType.Number, category: RecsType.String }, { metadata: { - name: "Tile", - types: ["u128", "u128", "u128", "u128", "u128", "u64", "u8"], - customTypes: [], + name: "eternum-Structure", + types: ["u32", "enum"], + customTypes: ["StructureCategory"], }, }, ); })(), - TickConfig: (() => { + StructureCount: (() => { return defineComponent( world, + { coord: { x: RecsType.Number, y: RecsType.Number }, count: RecsType.Number }, { - config_id: RecsType.BigInt, - tick_id: RecsType.Number, - tick_interval_in_seconds: RecsType.Number, + metadata: { + name: "eternum-StructureCount", + types: ["u32", "u32", "u8"], + customTypes: ["Coord"], + }, }, + ); + })(), + TickConfig: (() => { + return defineComponent( + world, + { config_id: RecsType.Number, tick_id: RecsType.Number, tick_interval_in_seconds: RecsType.BigInt }, { metadata: { - name: "TickConfig", - types: ["u128", "u8", "u64"], + name: "eternum-TickConfig", + types: ["u32", "u8", "u64"], customTypes: [], }, }, ); })(), - StaminaConfig: (() => { + Tile: (() => { return defineComponent( world, { - config_id: RecsType.BigInt, - unit_type: RecsType.Number, - max_stamina: RecsType.Number, + col: RecsType.Number, + row: RecsType.Number, + explored_by_id: RecsType.Number, + explored_at: RecsType.BigInt, + biome: RecsType.String, }, { metadata: { - name: "StaminaConfig", - types: ["u128", "u8", "u16"], - customTypes: [], + name: "eternum-Tile", + types: ["u32", "u32", "u32", "u64", "enum"], + customTypes: ["Biome"], }, }, ); })(), - Stamina: (() => { + Trade: (() => { return defineComponent( world, { - entity_id: RecsType.BigInt, - amount: RecsType.Number, - last_refill_tick: RecsType.Number, + trade_id: RecsType.Number, + maker_id: RecsType.Number, + maker_gives_resources_id: RecsType.Number, + maker_gives_resources_hash: RecsType.BigInt, + maker_gives_resources_weight: RecsType.BigInt, + taker_id: RecsType.Number, + taker_gives_resources_id: RecsType.Number, + taker_gives_resources_hash: RecsType.BigInt, + taker_gives_resources_weight: RecsType.BigInt, + expires_at: RecsType.BigInt, }, { metadata: { - name: "Stamina", - types: ["u128", "u16", "u64"], + name: "eternum-Trade", + types: ["u32", "u32", "u32", "felt252", "u128", "u32", "u32", "felt252", "u128", "u64"], customTypes: [], }, }, ); })(), - Guild: (() => { + TroopConfig: (() => { return defineComponent( world, { - entity_id: RecsType.BigInt, - is_public: RecsType.Boolean, - member_count: RecsType.Number, + config_id: RecsType.Number, + health: RecsType.Number, + knight_strength: RecsType.Number, + paladin_strength: RecsType.Number, + crossbowman_strength: RecsType.Number, + advantage_percent: RecsType.Number, + disadvantage_percent: RecsType.Number, + pillage_health_divisor: RecsType.Number, + army_free_per_structure: RecsType.Number, + army_extra_per_building: RecsType.Number, }, { metadata: { - name: "Guild", - types: ["u128", "bool", "u16"], + name: "eternum-TroopConfig", + types: ["u32", "u32", "u8", "u8", "u16", "u16", "u16", "u8", "u8", "u8"], customTypes: [], }, }, ); })(), - GuildMember: (() => { + Weight: (() => { return defineComponent( world, - { - address: RecsType.BigInt, - guild_entity_id: RecsType.BigInt, - }, + { entity_id: RecsType.Number, value: RecsType.BigInt }, { metadata: { - name: "GuildMember", - types: ["contractaddress", "u128"], + name: "eternum-Weight", + types: ["u32", "u128"], customTypes: [], }, }, ); })(), - GuildWhitelist: (() => { + WeightConfig: (() => { return defineComponent( world, { - address: RecsType.BigInt, - guild_entity_id: RecsType.BigInt, - is_whitelisted: RecsType.BigInt, + config_id: RecsType.Number, + weight_config_id: RecsType.Number, + entity_type: RecsType.Number, + weight_gram: RecsType.BigInt, }, { metadata: { - name: "GuildWhitelist", - types: ["contractaddress", "u128", "bool"], + name: "eternum-WeightConfig", + types: ["u32", "u32", "u32", "u128"], + customTypes: [], + }, + }, + ); + })(), + WorldConfig: (() => { + return defineComponent( + world, + { config_id: RecsType.Number, admin_address: RecsType.BigInt, realm_l2_contract: RecsType.BigInt }, + { + metadata: { + name: "eternum-WorldConfig", + types: ["u32", "contractaddress", "contractaddress"], customTypes: [], }, }, diff --git a/client/src/dojo/createSystemCalls.ts b/client/src/dojo/createSystemCalls.ts index e3c948dc5..d1deeb5ce 100644 --- a/client/src/dojo/createSystemCalls.ts +++ b/client/src/dojo/createSystemCalls.ts @@ -32,7 +32,7 @@ class PromiseQueue { } } -export type SystemCallFunctions = ReturnType; +type SystemCallFunctions = ReturnType; type SystemCallFunction = (...args: any[]) => any; type WrappedSystemCalls = Record; diff --git a/client/src/dojo/createUpdates.ts b/client/src/dojo/createUpdates.ts index 8a7346d5d..ba37fe017 100644 --- a/client/src/dojo/createUpdates.ts +++ b/client/src/dojo/createUpdates.ts @@ -1,34 +1,30 @@ -import { createEventSubscription } from "./events/createEventSubscription"; import { COMBAT_EVENT, CREATE_ORDER_EVENT, HYPERSTRUCTURE_FINISHED_EVENT, + ID, MAP_EXPLORED_EVENT, PILLAGE_EVENT, TRAVEL_EVENT, } from "@bibliothecadao/eternum"; import { numberToHex } from "../ui/utils/utils"; +import { createEventSubscription } from "./events/createEventSubscription"; export const createUpdates = async () => { const eventUpdates = { hyperstructureFinishedEvents: async () => createEventSubscription([HYPERSTRUCTURE_FINISHED_EVENT, "*"]), - createCombatEvents: async (entityId: bigint) => + createCombatEvents: async (entityId: ID) => createEventSubscription([COMBAT_EVENT, "*", numberToHex(Number(entityId)), "*"]), createTravelEvents: async (x: number, y: number) => createEventSubscription([TRAVEL_EVENT, numberToHex(x), numberToHex(y)]), - createDirectOffersEvents: async (entityId: bigint) => + createDirectOffersEvents: async (entityId: ID) => createEventSubscription([CREATE_ORDER_EVENT, numberToHex(Number(entityId)), "*"]), - createExploreMapEvents: async () => createEventSubscription([MAP_EXPLORED_EVENT], true, 1000, false), - createExploreEntityMapEvents: async (entityId: bigint) => - createEventSubscription([MAP_EXPLORED_EVENT, numberToHex(Number(entityId))], false), - createTravelHexEvents: async () => createEventSubscription([TRAVEL_EVENT], false), - createPillageHistoryEvents: async (structureId: bigint, attackerRealmEntityId: bigint) => - createEventSubscription( - [PILLAGE_EVENT, numberToHex(Number(structureId)), numberToHex(Number(attackerRealmEntityId))], - true, - 20, - false, - ), + createExploreMapEvents: async () => createEventSubscription([MAP_EXPLORED_EVENT], true, 1000), + createExploreEntityMapEvents: async (entityId: ID) => + createEventSubscription([MAP_EXPLORED_EVENT, numberToHex(Number(entityId))]), + createTravelHexEvents: async () => createEventSubscription([TRAVEL_EVENT]), + createPillageHistoryEvents: async (structureId: ID, attackerRealmEntityId: ID) => + createEventSubscription([PILLAGE_EVENT, numberToHex(structureId), numberToHex(attackerRealmEntityId)], true, 20), }; return { diff --git a/client/src/dojo/events/bankEventQueries.ts b/client/src/dojo/events/bankEventQueries.ts index 78ed6a2e3..38aaf88b3 100644 --- a/client/src/dojo/events/bankEventQueries.ts +++ b/client/src/dojo/events/bankEventQueries.ts @@ -1,9 +1,8 @@ -import { numberToHex } from "@/ui/utils/utils"; import { Event, client, getEventsQuery } from "./graphqlClient"; import { SWAP_EVENT } from "@bibliothecadao/eternum"; export const MAX_EVENTS = 5000; -export const ADMIN_BANK_ENTITY_ID = "0xde0b6b3a763fffe"; //999999999999999998n; +export const ADMIN_BANK_ENTITY_ID = "0x3b9ac9fe"; //999999998n; export interface BankStatsInterface { ownerTotalLordsFees: number; diff --git a/client/src/dojo/events/createEventSubscription.ts b/client/src/dojo/events/createEventSubscription.ts index 3a7b5159c..29723fa7c 100644 --- a/client/src/dojo/events/createEventSubscription.ts +++ b/client/src/dojo/events/createEventSubscription.ts @@ -1,6 +1,5 @@ import { gql } from "graphql-request"; import { ReplaySubject, Observable } from "rxjs"; -import { getLastLoginTimestamp } from "../../hooks/store/useNotificationsStore"; import { Event, client, getEventsQuery, wsClient } from "./graphqlClient"; const MAX_EVENTS = 50; @@ -9,7 +8,6 @@ export async function createEventSubscription( keys: string[], addPast: boolean = true, maxEvents: number = MAX_EVENTS, - filterTimestamp: boolean = true, ): Promise> { const lastUpdate$ = new ReplaySubject(); @@ -33,14 +31,7 @@ export async function createEventSubscription( const { events }: getEventsQuery = await client.request(queryBuilder); - const timestamps = getLastLoginTimestamp(); - let edges = events.edges; - if (filterTimestamp) { - edges.filter((event) => { - return dateToTimestamp(event.node.createdAt) > timestamps.lastLoginTimestamp; - }); - } edges.forEach((event) => { if (event.node) { lastUpdate$.next(event.node); @@ -80,9 +71,3 @@ export async function createEventSubscription( ); return lastUpdate$; } - -function dateToTimestamp(dateStr: string): number { - const date = new Date(`${dateStr}Z`); - let ts = Math.floor(date.getTime() / 1000); - return ts; -} diff --git a/client/src/dojo/events/hyperstructureEventQueries.ts b/client/src/dojo/events/hyperstructureEventQueries.ts index d72913c8a..8b34dc699 100644 --- a/client/src/dojo/events/hyperstructureEventQueries.ts +++ b/client/src/dojo/events/hyperstructureEventQueries.ts @@ -1,10 +1,10 @@ +import { HYPERSTRUCTURE_FINISHED_EVENT, ID } from "@bibliothecadao/eternum"; import { Event, client, getEventsQuery } from "./graphqlClient"; -import { HYPERSTRUCTURE_FINISHED_EVENT } from "@bibliothecadao/eternum"; -export const MAX_EVENTS = 5000; +const MAX_EVENTS = 5000; export interface HyperstructureEventInterface { - hyperstructureEntityId: bigint; + hyperstructureEntityId: ID; timestamp: number; } @@ -36,7 +36,7 @@ export function parseHyperstructureFinishedEventData(eventData: Event): Hyperstr const [hyperstructureEntityId, timestamp] = eventData.data; return { - hyperstructureEntityId: BigInt(hyperstructureEntityId), + hyperstructureEntityId: hyperstructureEntityId, timestamp: Number(timestamp), }; } diff --git a/client/src/dojo/events/pillageEventQueries.ts b/client/src/dojo/events/pillageEventQueries.ts index 9d8df67ae..130da6c52 100644 --- a/client/src/dojo/events/pillageEventQueries.ts +++ b/client/src/dojo/events/pillageEventQueries.ts @@ -1,8 +1,8 @@ import { numberToHex } from "@/ui/utils/utils"; +import { ID, PILLAGE_EVENT } from "@bibliothecadao/eternum"; import { client, getEventsQuery } from "./graphqlClient"; -import { PILLAGE_EVENT } from "@bibliothecadao/eternum"; -export async function getPillageEvents(realmId: bigint): Promise { +export async function getPillageEvents(realmId: ID): Promise { const query = ` query { events(keys: ["${PILLAGE_EVENT}","*","${numberToHex(Number(realmId))}"]) { diff --git a/client/src/dojo/modelManager/BattleManager.ts b/client/src/dojo/modelManager/BattleManager.ts index 77d6cf63f..e3a11dfe0 100644 --- a/client/src/dojo/modelManager/BattleManager.ts +++ b/client/src/dojo/modelManager/BattleManager.ts @@ -2,27 +2,26 @@ import { DojoResult } from "@/hooks/context/DojoContext"; import { ArmyInfo } from "@/hooks/helpers/useArmies"; import { Structure } from "@/hooks/helpers/useStructures"; import { Health } from "@/types"; -import { BattleSide, EternumGlobalConfig, StructureType } from "@bibliothecadao/eternum"; +import { BattleSide, EternumGlobalConfig, ID, StructureType } from "@bibliothecadao/eternum"; import { ComponentValue, Components, Has, HasValue, getComponentValue, runQuery } from "@dojoengine/recs"; import { getEntityIdFromKeys } from "@dojoengine/utils"; import { ClientComponents } from "../createClientComponents"; export enum BattleType { - None, Hex, Structure, Realm, } export class BattleManager { - battleId: bigint; + battleEntityId: ID; dojo: DojoResult; battleType: BattleType | undefined; private battleIsClaimable: boolean | undefined; private battleIsRaidable: boolean | undefined; - constructor(battleId: bigint, dojo: DojoResult) { - this.battleId = battleId; + constructor(battleEntityId: ID, dojo: DojoResult) { + this.battleEntityId = battleEntityId; this.dojo = dojo; } @@ -90,7 +89,7 @@ export class BattleManager { } public getBattle(): ComponentValue | undefined { - return getComponentValue(this.dojo.setup.components.Battle, getEntityIdFromKeys([this.battleId])); + return getComponentValue(this.dojo.setup.components.Battle, getEntityIdFromKeys([BigInt(this.battleEntityId)])); } public getUpdatedArmy( @@ -217,7 +216,7 @@ export class BattleManager { if (this.battleIsRaidable) return this.battleIsRaidable; - if (this.isBattleOngoing(currentTimestamp) && selectedArmy.battle_id !== this.battleId) { + if (this.isBattleOngoing(currentTimestamp) && selectedArmy.battle_id !== this.battleEntityId) { return false; } @@ -254,17 +253,17 @@ export class BattleManager { return ( runQuery([ Has(this.dojo.setup.components.Army), - HasValue(this.dojo.setup.components.Army, { battle_id: this.battleId }), + HasValue(this.dojo.setup.components.Army, { battle_id: this.battleEntityId }), ]).size === 0 ); } - public async pillageStructure(raider: ArmyInfo, structureEntityId: bigint) { - if (this.battleId !== 0n && this.battleId === raider.battle_id) { + public async pillageStructure(raider: ArmyInfo, structureEntityId: ID) { + if (this.battleEntityId !== 0 && this.battleEntityId === raider.battle_id) { await this.dojo.setup.systemCalls.battle_leave_and_pillage({ signer: this.dojo.account.account, army_id: raider.entity_id, - battle_id: this.battleId, + battle_id: this.battleEntityId, structure_id: structureEntityId, }); } else { diff --git a/client/src/dojo/modelManager/MarketManager.ts b/client/src/dojo/modelManager/MarketManager.ts index 7091dae00..bf6d6198b 100644 --- a/client/src/dojo/modelManager/MarketManager.ts +++ b/client/src/dojo/modelManager/MarketManager.ts @@ -1,6 +1,6 @@ -import { Component, OverridableComponent, getComponentValue } from "@dojoengine/recs"; import { getEntityIdFromKeys } from "@/ui/utils/utils"; -import { EternumGlobalConfig } from "@bibliothecadao/eternum"; +import { ContractAddress, EternumGlobalConfig, ID, ResourcesIds } from "@bibliothecadao/eternum"; +import { Component, OverridableComponent, getComponentValue } from "@dojoengine/recs"; import { ClientComponents } from "../createClientComponents"; export class MarketManager { @@ -10,9 +10,9 @@ export class MarketManager { liquidityModel: | Component | OverridableComponent; - bankEntityId: bigint; - player: bigint; - resourceId: bigint; + bankEntityId: ID; + player: ContractAddress; + resourceId: ResourcesIds; constructor( marketModel: @@ -21,9 +21,9 @@ export class MarketManager { liquidityModel: | Component | OverridableComponent, - bankEntityId: bigint, - player: bigint, - resourceId: bigint, + bankEntityId: ID, + player: ContractAddress, + resourceId: ResourcesIds, ) { this.marketModel = marketModel; this.liquidityModel = liquidityModel; @@ -40,12 +40,15 @@ export class MarketManager { public getLiquidity() { return getComponentValue( this.liquidityModel, - getEntityIdFromKeys([this.bankEntityId, this.player, this.resourceId]), + getEntityIdFromKeys([BigInt(this.bankEntityId), this.player, BigInt(this.resourceId)]), ); } public getMarket() { - return getComponentValue(this.marketModel, getEntityIdFromKeys([this.bankEntityId, this.resourceId])); + return getComponentValue( + this.marketModel, + getEntityIdFromKeys([BigInt(this.bankEntityId), BigInt(this.resourceId)]), + ); } public getSharesScaled = () => { diff --git a/client/src/dojo/modelManager/ProductionManager.ts b/client/src/dojo/modelManager/ProductionManager.ts index dbe2bea40..b8fa6ec5c 100644 --- a/client/src/dojo/modelManager/ProductionManager.ts +++ b/client/src/dojo/modelManager/ProductionManager.ts @@ -2,7 +2,9 @@ import { getEntityIdFromKeys } from "@/ui/utils/utils"; import { BuildingType, EternumGlobalConfig, + ID, RESOURCE_INPUTS_SCALED, + ResourcesIds, STOREHOUSE_CAPACITY, } from "@bibliothecadao/eternum"; import { Component, OverridableComponent, getComponentValue } from "@dojoengine/recs"; @@ -18,8 +20,8 @@ export class ProductionManager { buildingQuantity: | Component | OverridableComponent; - entityId: bigint; - resourceId: bigint; + entityId: ID; + resourceId: ResourcesIds; constructor( productionModel: @@ -31,8 +33,8 @@ export class ProductionManager { buildingQuantity: | Component | OverridableComponent, - entityId: bigint, - resourceId: bigint, + entityId: ID, + resourceId: ResourcesIds, ) { this.productionModel = productionModel; this.buildingQuantity = buildingQuantity; @@ -41,7 +43,6 @@ export class ProductionManager { this.resourceModel = resourceModel; } - // Retrieves the production data for the current entity public getProduction() { return this._getProduction(this.resourceId); } @@ -104,8 +105,8 @@ export class ProductionManager { const quantity = getComponentValue( this.buildingQuantity, - getEntityIdFromKeys([BigInt(this.entityId || "0"), BigInt(BuildingType.Storehouse)]), - )?.value || "0"; + getEntityIdFromKeys([BigInt(this.entityId || 0), BigInt(BuildingType.Storehouse)]), + )?.value || 0; return ( (Number(quantity) * STOREHOUSE_CAPACITY + STOREHOUSE_CAPACITY) * EternumGlobalConfig.resources.resourcePrecision ); @@ -117,7 +118,7 @@ export class ProductionManager { return production?.production_rate > 0n && !this._inputs_available(currentTick, this.resourceId); } - private _balance(currentTick: number, resourceId: bigint): number { + private _balance(currentTick: number, resourceId: ResourcesIds): number { const resource = this._getResource(resourceId); const [sign, rate] = this._netRate(resourceId); @@ -142,7 +143,7 @@ export class ProductionManager { } } - private _productionDuration(currentTick: number, resourceId: bigint): number { + private _productionDuration(currentTick: number, resourceId: ResourcesIds): number { const production = this._getProduction(resourceId); if (!production) return 0; @@ -158,19 +159,19 @@ export class ProductionManager { } } - private _depletionDuration(currentTick: number, resourceId: bigint): number { + private _depletionDuration(currentTick: number, resourceId: ResourcesIds): number { const production = this._getProduction(resourceId); return Number(currentTick) - Number(production?.last_updated_tick); } - private _netRate(resourceId: bigint): [boolean, number] { + private _netRate(resourceId: ResourcesIds): [boolean, number] { const production = this._getProduction(resourceId); if (!production) return [false, 0]; const difference = Number(production.production_rate) - Number(production.consumption_rate); return [difference > 0, difference]; } - private _balanceExhaustionTick(currentTick: number, resourceId: bigint): number { + private _balanceExhaustionTick(currentTick: number, resourceId: ResourcesIds): number { const production = this._getProduction(resourceId); const resource = this._getResource(resourceId); @@ -197,8 +198,8 @@ export class ProductionManager { } } - private _inputs_available(currentTick: number, resourceId: bigint): boolean { - const inputs = RESOURCE_INPUTS_SCALED[Number(resourceId.toString())]; + private _inputs_available(currentTick: number, resourceId: ResourcesIds): boolean { + const inputs = RESOURCE_INPUTS_SCALED[resourceId]; // Ensure inputs is an array before proceeding if (inputs.length == 0) { @@ -206,7 +207,7 @@ export class ProductionManager { } for (const input of inputs) { - const balance = this._balance(currentTick, BigInt(input.resource)); + const balance = this._balance(currentTick, input.resource); if (balance === undefined || balance <= 0) { return false; } @@ -214,11 +215,11 @@ export class ProductionManager { return true; } - private _getProduction(resourceId: bigint) { - return getComponentValue(this.productionModel, getEntityIdFromKeys([this.entityId, resourceId])); + private _getProduction(resourceId: ResourcesIds) { + return getComponentValue(this.productionModel, getEntityIdFromKeys([BigInt(this.entityId), BigInt(resourceId)])); } - private _getResource(resourceId: bigint) { - return getComponentValue(this.resourceModel, getEntityIdFromKeys([this.entityId, resourceId])); + private _getResource(resourceId: ResourcesIds) { + return getComponentValue(this.resourceModel, getEntityIdFromKeys([BigInt(this.entityId), BigInt(resourceId)])); } } diff --git a/client/src/dojo/modelManager/__tests__/BattleManager.test.ts b/client/src/dojo/modelManager/__tests__/BattleManager.test.ts index 555c02222..116b3acf7 100644 --- a/client/src/dojo/modelManager/__tests__/BattleManager.test.ts +++ b/client/src/dojo/modelManager/__tests__/BattleManager.test.ts @@ -47,13 +47,13 @@ const mockDojoResult = { describe("basic functionalities", () => { it("should return a valid object", () => { - const battleManager = new BattleManager(0n, mockDojoResult); + const battleManager = new BattleManager(0, mockDojoResult); expect(battleManager).toBeDefined(); }); - it("should return a valid battleId", () => { + it("should return a valid battleEntityId", () => { const battleManager = new BattleManager(BATTLE_ENTITY_ID, mockDojoResult); - expect(battleManager.battleId).toBe(BATTLE_ENTITY_ID); + expect(battleManager.battleEntityId).toBe(BATTLE_ENTITY_ID); }); }); @@ -63,7 +63,7 @@ describe("getBattle", () => { vi.mocked(getComponentValue).mockReturnValueOnce(mockBattle); - const battleManager = new BattleManager(10n, mockDojoResult); + const battleManager = new BattleManager(BATTLE_ENTITY_ID, mockDojoResult); const battle = battleManager.getBattle(); expect(battle).toBeDefined(); @@ -75,7 +75,7 @@ describe("isBattle", () => { it("should return true for a defined battle object", () => { vi.mocked(getComponentValue).mockReturnValueOnce(generateMockBatle(true)); - const battleManager = new BattleManager(10n, mockDojoResult); + const battleManager = new BattleManager(BATTLE_ENTITY_ID, mockDojoResult); expect(battleManager.isBattle()).toBe(true); }); @@ -83,14 +83,14 @@ describe("isBattle", () => { it("should return false for a undefined battle object", () => { vi.mocked(getComponentValue).mockReturnValueOnce(undefined); - const battleManager = new BattleManager(10n, mockDojoResult); + const battleManager = new BattleManager(BATTLE_ENTITY_ID, mockDojoResult); expect(battleManager.isBattle()).toBe(false); }); }); describe("getElapsedTime", () => { - const battleManager = new BattleManager(10n, mockDojoResult); + const battleManager = new BattleManager(BATTLE_ENTITY_ID, mockDojoResult); it("should return 0 for undefined battle", () => { vi.mocked(getComponentValue).mockReturnValueOnce(undefined); @@ -118,7 +118,7 @@ describe("getElapsedTime", () => { }); describe("isBattleOngoing", () => { - const battleManager = new BattleManager(10n, mockDojoResult); + const battleManager = new BattleManager(BATTLE_ENTITY_ID, mockDojoResult); it("should return false for an undefined object", () => { vi.mocked(getComponentValue).mockReturnValueOnce(undefined); @@ -146,7 +146,7 @@ describe("isBattleOngoing", () => { }); describe("getUpdatedHealth", () => { - const battleManager = new BattleManager(0n, mockDojoResult); + const battleManager = new BattleManager(0, mockDojoResult); it("should return less health if time has passed", () => { const currentHealth = { current: 10n, lifetime: 10n }; @@ -157,7 +157,7 @@ describe("getUpdatedHealth", () => { it("should return the same health if time hasn't passed", () => { const currentHealth = 10n; - const health = { current: currentHealth, lifetime: 10n }; + const health = { current: currentHealth, lifetime: currentHealth }; const updatedHealth = battleManager["getUdpdatedHealth"](1n, health, 0); @@ -166,7 +166,7 @@ describe("getUpdatedHealth", () => { it("should return the same health if delta is 0", () => { const currentHealth = 10n; - const health = { current: currentHealth, lifetime: 10n }; + const health = { current: currentHealth, lifetime: currentHealth }; const updatedHealth = battleManager["getUdpdatedHealth"](0n, health, 1000); @@ -175,7 +175,7 @@ describe("getUpdatedHealth", () => { it("should return 0 if damages exceed current health", () => { const currentHealth = 10n; - const health = { current: currentHealth, lifetime: 10n }; + const health = { current: currentHealth, lifetime: currentHealth }; const updatedHealth = battleManager["getUdpdatedHealth"](2n, health, 10); @@ -184,7 +184,7 @@ describe("getUpdatedHealth", () => { it("should return 0 if damages equal current health", () => { const currentHealth = 10n; - const health = { current: currentHealth, lifetime: 10n }; + const health = { current: currentHealth, lifetime: currentHealth }; const updatedHealth = battleManager["getUdpdatedHealth"](1n, health, 10); @@ -193,7 +193,7 @@ describe("getUpdatedHealth", () => { }); describe("getUpdatedTroops", () => { - const battleManager = new BattleManager(0n, mockDojoResult); + const battleManager = new BattleManager(0, mockDojoResult); it("should return 0 troops if lifetime is 0", () => { const currentHealth = { current: 0n, lifetime: 0n }; @@ -270,7 +270,7 @@ describe("getUpdatedTroops", () => { }); describe("updateHealth", () => { - const battleManager = new BattleManager(0n, mockDojoResult); + const battleManager = new BattleManager(0, mockDojoResult); it("health should be less than initial if time passed between last updated and current timestamp", () => { const battle = generateMockBatle(true); @@ -307,7 +307,7 @@ describe("updateHealth", () => { }); describe("getUpdatedBattle", () => { - const battleManager = new BattleManager(0n, mockDojoResult); + const battleManager = new BattleManager(0, mockDojoResult); it("return should be undefined if battle is undefined", () => { const currentTimestamp = 0; @@ -519,7 +519,7 @@ describe("getBattleType", () => { }); describe("isEmpty", () => { - const battleManager = new BattleManager(0n, mockDojoResult); + const battleManager = new BattleManager(0, mockDojoResult); it("Should be considered as empty if the array is length 0", () => { vi.mocked(runQuery).mockReturnValueOnce(new Set()); diff --git a/client/src/dojo/modelManager/__tests__/__mock__.ts b/client/src/dojo/modelManager/__tests__/__mock__.ts index 124862914..c7a72e00a 100644 --- a/client/src/dojo/modelManager/__tests__/__mock__.ts +++ b/client/src/dojo/modelManager/__tests__/__mock__.ts @@ -1,12 +1,15 @@ +import { ClientComponents } from "@/dojo/createClientComponents"; import { ArmyInfo } from "@/hooks/helpers/useArmies"; -import { BattleSide, StructureType } from "@bibliothecadao/eternum"; +import { Structure } from "@/hooks/helpers/useStructures"; +import { BattleSide, ID, StructureType } from "@bibliothecadao/eternum"; +import { ComponentValue } from "@dojoengine/recs"; export const CURRENT_TIMESTAMP = 2; export const DURATION_LEFT_IF_ONGOING = 1000n; export const LAST_UPDATED = 0n; -export const ARMY_ENTITY_ID = 1n; -export const BATTLE_ENTITY_ID = 10n; +export const ARMY_ENTITY_ID = 1; +export const BATTLE_ENTITY_ID = 10; const getTroopHeathSimplified = (troopCount: bigint): bigint => { return troopCount * 2n; @@ -18,18 +21,22 @@ export const BATTLE_INITIAL_HEALTH = getTroopHeathSimplified(BATTLE_TROOP_COUNT) export const ARMY_TROOP_COUNT = 5n; export const ARMY_INITIAL_HEALTH = getTroopHeathSimplified(ARMY_TROOP_COUNT); -export const generateMockBatle = (isOngoing: boolean, lastUpdated?: number, loser?: BattleSide) => { +export const generateMockBatle = ( + isOngoing: boolean, + lastUpdated?: number, + loser?: BattleSide, +): ComponentValue => { return { entity_id: BATTLE_ENTITY_ID, attack_army: { troops: { knight_count: BATTLE_TROOP_COUNT, paladin_count: BATTLE_TROOP_COUNT, crossbowman_count: 0n }, - battle_id: 0n, - battle_side: 0, + battle_id: 0, + battle_side: "Attack", }, defence_army: { troops: { knight_count: BATTLE_TROOP_COUNT, paladin_count: BATTLE_TROOP_COUNT, crossbowman_count: 0n }, - battle_id: 0n, - battle_side: 0, + battle_id: 0, + battle_side: "Defence", }, attack_army_lifetime: { troops: { @@ -37,8 +44,8 @@ export const generateMockBatle = (isOngoing: boolean, lastUpdated?: number, lose paladin_count: isOngoing ? 2n * BATTLE_TROOP_COUNT : BATTLE_TROOP_COUNT, crossbowman_count: isOngoing ? 2n * BATTLE_TROOP_COUNT : BATTLE_TROOP_COUNT, }, - battle_id: 0n, - battle_side: 0, + battle_id: 0, + battle_side: "Attack", }, defence_army_lifetime: { troops: { @@ -46,11 +53,11 @@ export const generateMockBatle = (isOngoing: boolean, lastUpdated?: number, lose paladin_count: isOngoing ? 2n * BATTLE_TROOP_COUNT : BATTLE_TROOP_COUNT, crossbowman_count: isOngoing ? 2n * BATTLE_TROOP_COUNT : BATTLE_TROOP_COUNT, }, - battle_id: 0n, - battle_side: 0, + battle_id: 0, + battle_side: "Defence", }, - attackers_resources_escrow_id: 0n, - defenders_resources_escrow_id: 0n, + attackers_resources_escrow_id: 0, + defenders_resources_escrow_id: 0, attack_army_health: { current: loser === BattleSide.Attack ? 0n : BATTLE_INITIAL_HEALTH, lifetime: BATTLE_INITIAL_HEALTH, @@ -66,10 +73,10 @@ export const generateMockBatle = (isOngoing: boolean, lastUpdated?: number, lose }; }; -export const generateMockArmyInfo = (alive?: boolean, isMine?: boolean, battleId?: bigint): ArmyInfo => { +export const generateMockArmyInfo = (alive?: boolean, isMine?: boolean, battleEntityId?: ID): ArmyInfo => { return { entity_id: ARMY_ENTITY_ID, - battle_id: battleId ?? BATTLE_ENTITY_ID, + battle_id: battleEntityId ?? BATTLE_ENTITY_ID, battle_side: BattleSide[BattleSide.Attack], troops: { knight_count: alive ? ARMY_TROOP_COUNT : 0n, @@ -84,8 +91,8 @@ export const generateMockArmyInfo = (alive?: boolean, isMine?: boolean, battleId offset: { x: 0, y: 0 }, position: { entity_id: ARMY_ENTITY_ID, x: 0, y: 0 }, owner: { entity_id: ARMY_ENTITY_ID, address: 0n }, - entityOwner: { entity_id: ARMY_ENTITY_ID, entity_owner_id: 0n }, - protectee: { army_id: ARMY_ENTITY_ID, protectee_id: 0n }, + entityOwner: { entity_id: ARMY_ENTITY_ID, entity_owner_id: 0 }, + protectee: { army_id: ARMY_ENTITY_ID, protectee_id: 0 }, quantity: { entity_id: ARMY_ENTITY_ID, value: 10n }, movable: { entity_id: ARMY_ENTITY_ID, @@ -98,11 +105,11 @@ export const generateMockArmyInfo = (alive?: boolean, isMine?: boolean, battleId intermediate_coord_y: 0, }, capacity: { entity_id: ARMY_ENTITY_ID, weight_gram: 10n }, - arrivalTime: { entity_id: ARMY_ENTITY_ID, arrives_at: 0 }, - stamina: { entity_id: ARMY_ENTITY_ID, amount: 1, last_refill_tick: 0 }, + arrivalTime: { entity_id: ARMY_ENTITY_ID, arrives_at: 0n }, + stamina: { entity_id: ARMY_ENTITY_ID, amount: 1, last_refill_tick: 0n }, realm: { entity_id: ARMY_ENTITY_ID, - realm_id: 1n, + realm_id: 1, resource_types_packed: 1n, resource_types_count: 1, cities: 1, @@ -116,21 +123,21 @@ export const generateMockArmyInfo = (alive?: boolean, isMine?: boolean, battleId }; }; -export const generateMockStructure = (structureType: StructureType, isMine?: boolean) => { +export const generateMockStructure = (structureType: StructureType, isMine?: boolean): Structure => { return { - entity_id: 1n, + entity_id: 1, category: StructureType[structureType], isMine: isMine ?? false, isMercenary: false, name: "Mock Structure", protector: undefined, owner: { - entity_id: 1n, + entity_id: 1, address: 0n, }, entityOwner: { - entity_id: 1n, - entity_owner_id: 0n, + entity_id: 1, + entity_owner_id: 0, }, }; }; diff --git a/client/src/dojo/setupNetwork.ts b/client/src/dojo/setupNetwork.ts index 3ae7be69a..1a8b219b9 100644 --- a/client/src/dojo/setupNetwork.ts +++ b/client/src/dojo/setupNetwork.ts @@ -1,10 +1,10 @@ +import { EternumProvider } from "@bibliothecadao/eternum"; +import { DojoConfig } from "@dojoengine/core"; import { defineContractComponents } from "./contractComponents"; import { world } from "./world"; -import { DojoConfig } from "@dojoengine/core"; -import { EternumProvider } from "@bibliothecadao/eternum"; -import * as torii from "@dojoengine/torii-client"; import { BurnerManager } from "@dojoengine/create-burner"; +import * as torii from "@dojoengine/torii-client"; import { Account } from "starknet"; export type SetupNetworkResult = Awaited>; @@ -12,7 +12,7 @@ export type SetupNetworkResult = Awaited>; export async function setupNetwork({ ...config }: DojoConfig) { const provider = new EternumProvider(config.manifest, config.rpcUrl); - const toriiClient = await torii.createClient([], { + const toriiClient = await torii.createClient({ rpcUrl: config.rpcUrl, toriiUrl: config.toriiUrl, relayUrl: "", diff --git a/client/src/hooks/context/ChatContext.tsx b/client/src/hooks/context/ChatContext.tsx deleted file mode 100644 index c18d2f428..000000000 --- a/client/src/hooks/context/ChatContext.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { createContext, ReactNode, useContext } from "react"; -import { useLogin } from "../../ui/components/chat/Login"; -import { Client } from "@web3mq/client"; - -type ChatSetup = { - login: (didValue: string) => void; - init: () => void; - connect: () => void; - createKeyPairs: (didValue: string) => void; - register: (didValue: string) => void; - client: Client | null; - userId: string; - loginFlow: () => void; - loading: boolean; - loggedIn: boolean; -}; - -const ChatContext = createContext(null); - -type Props = { - children: ReactNode; -}; - -export const ChatProvider = ({ children }: Props) => { - const currentValue = useContext(ChatContext); - if (currentValue) throw new Error("DojoProvider can only be used once"); - - const { login, init, connect, createKeyPairs, register, client, userId, loginFlow, loading, loggedIn } = useLogin(); - - const contextValue: ChatSetup = { - login, // the provided setup - init, // create a new account - connect, // list all accounts - createKeyPairs, // get an account by id - register, // select an account by id - client, // the selected account - userId, - loginFlow, - loading, - loggedIn, - }; - - return {children}; -}; - -export const useChat = () => { - const value = useContext(ChatContext); - if (!value) throw new Error("Must be used within a DojoProvider"); - return value; -}; diff --git a/client/src/hooks/context/DojoContext.tsx b/client/src/hooks/context/DojoContext.tsx index fb9299cfd..f4e589c1c 100644 --- a/client/src/hooks/context/DojoContext.tsx +++ b/client/src/hooks/context/DojoContext.tsx @@ -16,7 +16,7 @@ interface DojoAccount { accountDisplay: string; } -export interface DojoContextType extends SetupResult { +interface DojoContextType extends SetupResult { masterAccount: Account | AccountInterface; account: DojoAccount; } @@ -83,7 +83,7 @@ export const useDojo = (): DojoResult => { }; }; -export const DojoContextProvider = ({ children, value }: DojoProviderProps) => { +const DojoContextProvider = ({ children, value }: DojoProviderProps) => { const currentValue = useContext(DojoContext); if (currentValue) throw new Error("DojoProvider can only be used once"); diff --git a/client/src/hooks/eventPoller.tsx b/client/src/hooks/eventPoller.tsx deleted file mode 100644 index 210406d4c..000000000 --- a/client/src/hooks/eventPoller.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { GraphQLClient } from "graphql-request"; - -const OFFSET = 100; - -export const client = new GraphQLClient(import.meta.env.VITE_TORII_GRAPHQL!); - -type getEventsQuery = { - events: { - totalCount: number; - edges: { - cursor: string; - node: Event; - }[]; - }; -}; - -export type Event = { - keys: string[]; - data: string[]; -}; - -// todo: put that in one other file -export const pollForEvents = async ( - keys: string[], - processResults: (event: Event) => void, - max?: number | undefined, -) => { - let cursor: string | undefined; - let shouldContinue = true; - let processedEvents = 0; - - const formattedKeys = keys.map((key) => `"${key}"`).join(","); - - while (shouldContinue && (max === undefined || processedEvents < max)) { - const queryBuilder = ` - query events { - events(keys:[${formattedKeys}] ${cursor ? `after: "${cursor}"` : ""} first: ${OFFSET}) { - totalCount - edges { - cursor - node { - keys - data - } - } - } - }`; - - const { events }: getEventsQuery = await client.request(queryBuilder); - - if (events.edges.length < OFFSET) { - shouldContinue = false; - } else { - cursor = events.edges[events.edges.length - 1].cursor; - } - - events.edges.forEach((edge) => { - processResults(edge.node); - processedEvents++; - }); - } -}; diff --git a/client/src/hooks/helpers/battles/__test__/useBattles.test.tsx b/client/src/hooks/helpers/battles/__test__/useBattles.test.tsx index f2d7989e1..636f67c93 100644 --- a/client/src/hooks/helpers/battles/__test__/useBattles.test.tsx +++ b/client/src/hooks/helpers/battles/__test__/useBattles.test.tsx @@ -23,7 +23,7 @@ describe("getBattle", () => { expect(battle).toBeUndefined(); }); - it("should return a battle for a valid battleId", () => { + it("should return a battle for a valid battleEntityId", () => { const mockBattle = generateMockBattle(true, true, false); vi.mocked(getComponentValue).mockReturnValueOnce(mockBattle); diff --git a/client/src/hooks/helpers/battles/__test__/useBattlesUtils.test.tsx b/client/src/hooks/helpers/battles/__test__/useBattlesUtils.test.tsx deleted file mode 100644 index 11da3323d..000000000 --- a/client/src/hooks/helpers/battles/__test__/useBattlesUtils.test.tsx +++ /dev/null @@ -1,113 +0,0 @@ -import { BattleSide } from "@bibliothecadao/eternum"; -import { Component, Entity, runQuery } from "@dojoengine/recs"; -import { describe, expect, it, vi } from "vitest"; -import * as testedModule from "../useBattlesUtils"; -import { generateMockArmy, generateMockBattle } from "./__mock__"; - -vi.mock("@dojoengine/recs", async () => { - const actual = await vi.importActual("@dojoengine/recs"); - return { - ...actual, - runQuery: vi.fn(), - }; -}); - -describe("protectorStillInBattle test", () => { - it("should return true for a single protector in the battle", () => { - const protectors = new Set(["0x0" as Entity]); - vi.mocked(runQuery).mockReturnValue(protectors); - - const isInBattle = testedModule.protectorStillInBattle({} as any, {} as any, {} as any); - expect(isInBattle).toBe(true); - }); - - it("should return false for no protector in the battle", () => { - const protectors = new Set([]); - vi.mocked(runQuery).mockReturnValue(protectors); - - const isInBattle = testedModule.protectorStillInBattle({} as any, {} as any, {} as any); - expect(isInBattle).toBe(false); - }); - - it("should return true for multiple protectors in the battle", () => { - const protectors = new Set(["0x1" as Entity, "0x2" as Entity]); - vi.mocked(runQuery).mockReturnValue(protectors); - - const isInBattle = testedModule.protectorStillInBattle({} as any, {} as any, {} as any); - expect(isInBattle).toBe(true); - }); -}); - -describe("armyHasLost test", () => { - it("should return false for an ongoing battle", () => { - const battle = generateMockBattle(true, true, false); - const army = generateMockArmy(BattleSide.Attack); - - const isLosingSide = testedModule.armyHasLost(army, battle); - expect(isLosingSide).toBe(false); - }); - - it("should return true for an ongoing battle", () => { - const battle = generateMockBattle(false, true, false); - const army = generateMockArmy(BattleSide.Attack); - - const isLosingSide = testedModule.armyHasLost(army, battle); - expect(isLosingSide).toBe(true); - }); - - it("should return false for an empty battle", () => { - const battle = generateMockBattle(false, true, false); - const army = generateMockArmy(BattleSide.Attack); - - const isLosingSide = testedModule.armyHasLost(army, battle); - expect(isLosingSide).toBe(true); - }); -}); - -describe("battleIsEmpty test", () => { - it("should return true when there are no attackers and defenders", () => { - const battle = generateMockBattle(true, true, false); - const Army = {} as Component; - - vi.mocked(runQuery).mockReturnValueOnce(new Set([])).mockReturnValueOnce(new Set([])); - - const isEmpty = testedModule.battleIsEmpty(Army, battle); - expect(isEmpty).toBe(true); - }); - - it("should return false when there are attackers", () => { - const battle = generateMockBattle(true, true, false); - const Army = {} as Component; - - vi.mocked(runQuery) - .mockReturnValueOnce(new Set(["0x1" as Entity])) - .mockReturnValueOnce(new Set([])); - - const isEmpty = testedModule.battleIsEmpty(Army, battle); - expect(isEmpty).toBe(false); - }); - - it("should return false when there are defenders", () => { - const battle = generateMockBattle(true, true, false); - const Army = {} as Component; - - vi.mocked(runQuery) - .mockReturnValueOnce(new Set([])) - .mockReturnValueOnce(new Set(["0x2" as Entity])); - - const isEmpty = testedModule.battleIsEmpty(Army, battle); - expect(isEmpty).toBe(false); - }); - - it("should return false when there are both attackers and defenders", () => { - const battle = generateMockBattle(true, true, false); - const Army = {} as Component; - - vi.mocked(runQuery) - .mockReturnValueOnce(new Set(["0x1" as Entity])) - .mockReturnValueOnce(new Set(["0x2" as Entity])); - - const isEmpty = testedModule.battleIsEmpty(Army, battle); - expect(isEmpty).toBe(false); - }); -}); diff --git a/client/src/hooks/helpers/battles/useBattles.tsx b/client/src/hooks/helpers/battles/useBattles.tsx index ecb123d71..e2b334484 100644 --- a/client/src/hooks/helpers/battles/useBattles.tsx +++ b/client/src/hooks/helpers/battles/useBattles.tsx @@ -1,6 +1,6 @@ import { ClientComponents } from "@/dojo/createClientComponents"; import { BattleManager } from "@/dojo/modelManager/BattleManager"; -import { EternumGlobalConfig, Position } from "@bibliothecadao/eternum"; +import { EternumGlobalConfig, ID, Position } from "@bibliothecadao/eternum"; import { useComponentValue, useEntityQuery } from "@dojoengine/react"; import { Component, @@ -9,20 +9,18 @@ import { Entity, Has, HasValue, - NotValue, getComponentValue, runQuery, } from "@dojoengine/recs"; import { getEntityIdFromKeys } from "@dojoengine/utils"; import { useMemo } from "react"; -import { shortString } from "starknet"; import { useDojo } from "../../context/DojoContext"; import * as module from "./useBattles"; -export type FullArmyType = ComponentValue & +type FullArmyType = ComponentValue & ComponentValue; -export type ExtraBattleInfo = ComponentValue & { +type ExtraBattleInfo = ComponentValue & { opponentArmy: FullArmyType; ownArmyEntityName: string; opponentArmyEntityName: string; @@ -34,10 +32,10 @@ export type BattleInfo = ComponentValue & }; export const getBattle = ( - battleId: Entity, + battleEntityId: Entity, Battle: Component, ): ComponentValue | undefined => { - let battle = getComponentValue(Battle, battleId); + let battle = getComponentValue(Battle, battleEntityId); let battleClone = structuredClone(battle); if (!battleClone) return; const multiplier = @@ -67,14 +65,14 @@ export const getExtraBattleInformation = ( .filter((item): item is BattleInfo => Boolean(item)); }; -export const useBattleManager = (battleId: bigint) => { +export const useBattleManager = (battleEntityId: ID) => { const dojo = useDojo(); - const battle = useComponentValue(dojo.setup.components.Battle, getEntityIdFromKeys([battleId])); + const battle = useComponentValue(dojo.setup.components.Battle, getEntityIdFromKeys([BigInt(battleEntityId)])); const battleManager = useMemo(() => { - return new BattleManager(battleId, dojo); - }, [battleId, battle]); + return new BattleManager(battleEntityId, dojo); + }, [battleEntityId, battle]); return battleManager; }; @@ -94,68 +92,6 @@ export const useAllBattles = () => { return allBattles; }; -export const usePlayerBattles = () => { - const { - account: { account }, - setup: { - components: { Battle, Army, Owner, Position, Structure }, - }, - } = useDojo(); - - const armiesEntityIds = useEntityQuery([Has(Army), HasValue(Owner, { address: BigInt(account.address) })]); - const playerBattles = (): ComponentValue[] => { - const battleEntityIds = armiesEntityIds - .map((armyEntityId: Entity) => { - const ownArmy = getComponentValue(Army, armyEntityId); - if (!ownArmy) return null; - const battle = module.getBattle(getEntityIdFromKeys([ownArmy.battle_id]), Battle); - if (!battle) return null; - return getEntityIdFromKeys([battle.entity_id]); - }) - .filter((entityId): entityId is Entity => entityId !== null); - return getExtraBattleInformation(battleEntityIds, Battle, Position, Structure); - }; - return { playerBattles }; -}; - -export const getBattleInfoByOwnArmyEntityId = (ownArmyEntityId: bigint): ExtraBattleInfo | undefined => { - const { - setup: { - components: { Army, Battle, Position, EntityName, Health }, - }, - } = useDojo(); - const ownArmy = getComponentValue(Army, getEntityIdFromKeys([ownArmyEntityId])); - if (!ownArmy) return; - const battle = module.getBattle(getEntityIdFromKeys([ownArmy.battle_id]), Battle); - if (!battle) return; - const position = getComponentValue(Position, getEntityIdFromKeys([ownArmy.entity_id])); - if (!position) return; - const ownArmyEntityName = getComponentValue(EntityName, getEntityIdFromKeys([ownArmyEntityId])); - const opponentArmyEntityId = runQuery([ - HasValue(Army, { battle_id: battle.entity_id }), - NotValue(Army, { entity_id: ownArmy.entity_id }), - ]) - .values() - .next().value; - - const opponentArmy = getComponentValue(Army, opponentArmyEntityId || ("" as Entity)); - if (!opponentArmy) return; - const opponentArmyHealth = getComponentValue(Health, opponentArmyEntityId!); - if (!opponentArmyHealth) return; - - const opponentArmyEntityName = getComponentValue(EntityName, opponentArmyEntityId!); - return { - ...position, - opponentArmy: { ...opponentArmy, ...opponentArmyHealth }, - ownArmyEntityName: ownArmyEntityName - ? shortString.decodeShortString(String(ownArmyEntityName?.name)) - : `Army ${ownArmy!.entity_id}`, - opponentArmyEntityName: opponentArmyEntityName - ? shortString.decodeShortString(String(opponentArmyEntityName?.name)) - : `Army ${opponentArmy!.entity_id}`, - }; -}; - export const useBattlesByPosition = ({ x, y }: Position) => { const { setup: { @@ -165,17 +101,3 @@ export const useBattlesByPosition = ({ x, y }: Position) => { const battleEntityIds = useEntityQuery([Has(Battle), HasValue(Position, { x, y })]); return getExtraBattleInformation(battleEntityIds, Battle, Position, Structure); }; - -export const getBattleByPosition = () => { - const { - setup: { - components: { Battle, Position, Structure }, - }, - } = useDojo(); - - const getBattle = ({ x, y }: Position) => { - const battleEntityIds = runQuery([Has(Battle), HasValue(Position, { x, y })]); - return getExtraBattleInformation(Array.from(battleEntityIds), Battle, Position, Structure)[0]; - }; - return getBattle; -}; diff --git a/client/src/hooks/helpers/battles/useBattlesUtils.tsx b/client/src/hooks/helpers/battles/useBattlesUtils.tsx deleted file mode 100644 index f375b6a9a..000000000 --- a/client/src/hooks/helpers/battles/useBattlesUtils.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { BattleSide } from "@bibliothecadao/eternum"; -import { Component, ComponentValue, Components, Has, HasValue, runQuery } from "@dojoengine/recs"; -import { BattleInfo } from "./useBattles"; - -export const battleIsFinished = (Army: Component, battle: BattleInfo) => { - const attackersEntityIds = getArmiesInBattleBySide(Army, battle, BattleSide.Attack); - const defendersEntityIds = getArmiesInBattleBySide(Army, battle, BattleSide.Defence); - - return ( - (Array.from(attackersEntityIds).length === 0 && battle.defence_army_health.current <= 0n) || - (Array.from(defendersEntityIds).length === 0 && battle.attack_army_health.current <= 0) - ); -}; - -export const battleIsEmpty = (Army: Component, battle: BattleInfo) => { - const attackersEntityIds = getArmiesInBattleBySide(Army, battle, BattleSide.Attack); - const defendersEntityIds = getArmiesInBattleBySide(Army, battle, BattleSide.Defence); - - return Array.from(attackersEntityIds).length === 0 && Array.from(defendersEntityIds).length === 0; -}; - -export const armyHasLost = (army: ComponentValue, battle: BattleInfo) => { - if (army.battle_id !== battle.entity_id) { - throw new Error("Army not in the correct battle"); - } - return ( - (army.battle_side === BattleSide.Attack && BigInt(battle.attack_army_health.current) <= 0) || - (army.battle_side === BattleSide.Defence && BigInt(battle.defence_army_health.current) <= 0) - ); -}; - -export const protectorStillInBattle = (Army: Component, Protectee: Component, battle: BattleInfo) => { - const protectorEntityIds = getProtectorsInBattle(Army, Protectee, battle); - return Array.from(protectorEntityIds).length > 0; -}; - -export const getProtectorsInBattle = (Army: Component, Protectee: Component, battle: BattleInfo) => { - return runQuery([Has(Protectee), HasValue(Army, { battle_id: battle.entity_id, battle_side: "Defence" })]); -}; - -export const getArmiesInBattleBySide = (Army: Component, battle: BattleInfo, battle_side: BattleSide) => { - return runQuery([Has(Army), HasValue(Army, { battle_id: battle.entity_id, battle_side: BattleSide[battle_side] })]); -}; diff --git a/client/src/hooks/helpers/useArmies.tsx b/client/src/hooks/helpers/useArmies.tsx index fd947c6d3..0024cd05b 100644 --- a/client/src/hooks/helpers/useArmies.tsx +++ b/client/src/hooks/helpers/useArmies.tsx @@ -1,6 +1,6 @@ import { ClientComponents } from "@/dojo/createClientComponents"; import { getUIPositionFromColRow } from "@/ui/utils/utils"; -import { EternumGlobalConfig, Position, UIPosition } from "@bibliothecadao/eternum"; +import { ContractAddress, EternumGlobalConfig, ID, Position, UIPosition } from "@bibliothecadao/eternum"; import { useEntityQuery } from "@dojoengine/react"; import { Component, @@ -17,8 +17,6 @@ import { getEntityIdFromKeys } from "@dojoengine/utils"; import { useMemo } from "react"; import { shortString } from "starknet"; import { useDojo } from "../context/DojoContext"; -import { BattleInfo, getBattle } from "./battles/useBattles"; -import { armyHasLost, battleIsFinished } from "./battles/useBattlesUtils"; export type ArmyInfo = ComponentValue & { name: string; @@ -40,7 +38,7 @@ export type ArmyInfo = ComponentValue & { homePosition: ComponentValue | undefined; }; -export const formatArmies = ( +const formatArmies = ( armies: Entity[], playerAddress: string, Army: Component, @@ -71,7 +69,7 @@ export const formatArmies = ( let owner = getComponentValue(Owner, armyEntityId); if (!owner && entityOwner?.entity_owner_id) { - owner = getComponentValue(Owner, getEntityIdFromKeys([entityOwner.entity_owner_id])); + owner = getComponentValue(Owner, getEntityIdFromKeys([BigInt(entityOwner.entity_owner_id)])); } if (!owner) return undefined; @@ -97,10 +95,10 @@ export const formatArmies = ( const arrivalTime = getComponentValue(ArrivalTime, armyEntityId); const stamina = getComponentValue(Stamina, armyEntityId); const name = getComponentValue(Name, armyEntityId); - const realm = entityOwner && getComponentValue(Realm, getEntityIdFromKeys([entityOwner.entity_owner_id])); - const homePosition = realm && getComponentValue(Position, getEntityIdFromKeys([realm.realm_id])); + const realm = entityOwner && getComponentValue(Realm, getEntityIdFromKeys([BigInt(entityOwner.entity_owner_id)])); + const homePosition = realm && getComponentValue(Position, getEntityIdFromKeys([BigInt(realm.realm_id)])); - const isMine = BigInt(owner?.address || 0) === BigInt(playerAddress); + const isMine = (owner?.address || 0n) === ContractAddress(playerAddress); const isMercenary = owner === undefined; const ownGroupIndex = Number(army.entity_id) % 12; const offset = calculateOffset(ownGroupIndex, 12); @@ -161,7 +159,7 @@ export const useMovableArmies = () => { Has(Health), Not(Protectee), NotValue(Movable, { sec_per_km: 0 }), - HasValue(Army, { battle_id: 0n }), + HasValue(Army, { battle_id: 0 }), ]); return { @@ -186,7 +184,7 @@ export const useMovableArmies = () => { }; }; -export const useArmiesByEntityOwner = ({ entity_owner_entity_id }: { entity_owner_entity_id: bigint }) => { +export const useArmiesByEntityOwner = ({ entity_owner_entity_id }: { entity_owner_entity_id: ID }) => { const { setup: { components: { @@ -235,48 +233,6 @@ export const useArmiesByEntityOwner = ({ entity_owner_entity_id }: { entity_owne }; }; -export const useArmiesByBattleId = (battle_id: bigint) => { - const { - setup: { - components: { - Position, - EntityOwner, - Owner, - Health, - Quantity, - Movable, - Capacity, - ArrivalTime, - Realm, - Army, - Protectee, - EntityName, - Stamina, - }, - }, - account: { account }, - } = useDojo(); - - const armiesEntityIds = useEntityQuery([HasValue(Army, { battle_id: battle_id }), NotValue(Army, { battle_id: 0n })]); - return formatArmies( - Array.from(armiesEntityIds), - account.address, - Army, - Protectee, - EntityName, - Health, - Quantity, - Movable, - Capacity, - ArrivalTime, - Position, - EntityOwner, - Owner, - Realm, - Stamina, - ); -}; - export const getArmiesByBattleId = () => { const { setup: { @@ -299,7 +255,7 @@ export const getArmiesByBattleId = () => { account: { account }, } = useDojo(); - const armiesByBattleId = (battle_id: bigint) => { + const armiesByBattleId = (battle_id: ID) => { const armiesEntityIds = runQuery([HasValue(Army, { battle_id })]); return formatArmies( Array.from(armiesEntityIds), @@ -322,7 +278,7 @@ export const getArmiesByBattleId = () => { return armiesByBattleId; }; -export const useArmyByArmyEntityId = (entityId: bigint) => { +export const useArmyByArmyEntityId = (entityId: ID) => { const { setup: { components: { @@ -364,7 +320,7 @@ export const useArmyByArmyEntityId = (entityId: bigint) => { )[0]; }; -export const getUserArmyInBattle = (battle_id: bigint) => { +export const getUserArmyInBattle = (battle_id: ID) => { const { account: { account }, setup: { @@ -388,9 +344,9 @@ export const getUserArmyInBattle = (battle_id: bigint) => { const armiesEntityIds = runQuery([ Has(Army), - NotValue(Army, { battle_id: 0n }), - HasValue(Army, { battle_id: battle_id }), - HasValue(Owner, { address: BigInt(account.address) }), + NotValue(Army, { battle_id: 0 }), + HasValue(Army, { battle_id }), + HasValue(Owner, { address: ContractAddress(account.address) }), ]); const armies = useMemo(() => { @@ -443,8 +399,8 @@ export const useOwnArmiesByPosition = ({ position, inBattle }: { position: Posit Has(Army), HasValue(Position, { x: position.x, y: position.y }), Not(Protectee), - HasValue(Owner, { address: BigInt(account.address) }), - inBattle ? NotValue(Army, { battle_id: 0n }) : HasValue(Army, { battle_id: 0n }), + HasValue(Owner, { address: ContractAddress(account.address) }), + inBattle ? NotValue(Army, { battle_id: 0 }) : HasValue(Army, { battle_id: 0 }), ]); const ownArmies = useMemo(() => { @@ -498,7 +454,7 @@ export const useEnemyArmiesByPosition = ({ position }: { position: Position }) = Has(Army), HasValue(Position, { x: position.x, y: position.y }), Not(Protectee), - NotValue(Owner, { address: BigInt(account.address) }), + NotValue(Owner, { address: ContractAddress(account.address) }), ]); const enemyArmies = useMemo(() => { @@ -547,7 +503,7 @@ export const getArmyByEntityId = () => { account: { account }, } = useDojo(); - const getAliveArmy = (entity_id: bigint): ArmyInfo | undefined => { + const getAliveArmy = (entity_id: ID): ArmyInfo | undefined => { const armiesEntityIds = runQuery([Has(Army), HasValue(Army, { entity_id: entity_id })]); return formatArmies( @@ -569,7 +525,7 @@ export const getArmyByEntityId = () => { )[0]; }; - const getArmy = (entity_id: bigint) => { + const getArmy = (entity_id: ID) => { const armiesEntityIds = runQuery([Has(Army), HasValue(Army, { entity_id: entity_id })]); return formatArmies( @@ -617,18 +573,18 @@ export const getArmiesAtPosition = () => { } = useDojo(); const armiesAtPosition = ({ x, y }: Position) => { - const allArmiesAtPosition = runQuery([Has(Army), HasValue(Position, { x, y }), HasValue(Army, { battle_id: 0n })]); + const allArmiesAtPosition = runQuery([Has(Army), HasValue(Position, { x, y }), HasValue(Army, { battle_id: 0 })]); const userArmies = Array.from(allArmiesAtPosition).filter((armyEntityId: any) => { const entityOwner = getComponentValue(EntityOwner, armyEntityId); - const owner = getComponentValue(Owner, getEntityIdFromKeys([entityOwner?.entity_owner_id || 0n])); - return owner?.address === BigInt(account.address); + const owner = getComponentValue(Owner, getEntityIdFromKeys([BigInt(entityOwner?.entity_owner_id || 0)])); + return owner?.address === ContractAddress(account.address); }); const opponentArmies = Array.from(allArmiesAtPosition).filter((armyEntityId: any) => { const entityOwner = getComponentValue(EntityOwner, armyEntityId); - const owner = getComponentValue(Owner, getEntityIdFromKeys([entityOwner?.entity_owner_id || 0n])); - return owner?.address !== BigInt(account.address); + const owner = getComponentValue(Owner, getEntityIdFromKeys([BigInt(entityOwner?.entity_owner_id || 0)])); + return owner?.address !== ContractAddress(account.address); }); return { @@ -691,16 +647,3 @@ const calculateOffset = (index: number, total: number) => { y: offsetRadius * Math.sin(angle), }; }; - -export const checkIfArmyLostAFinishedBattle = (Battle: Component, Army: Component, army: ArmyInfo) => { - const battle = getBattle(getEntityIdFromKeys([army?.battle_id || 0n]), Battle); - if (battle && armyHasLost(army, battle as BattleInfo) && battleIsFinished(Army, battle as BattleInfo)) { - return true; - } - return false; -}; - -export const checkIfArmyAliveOnchain = (army: ArmyInfo) => { - if (army.protectee !== undefined) return true; - return army.health.current > 0n; -}; diff --git a/client/src/hooks/helpers/useBanks.tsx b/client/src/hooks/helpers/useBanks.tsx index 6c2b4b85c..01db9d8f1 100644 --- a/client/src/hooks/helpers/useBanks.tsx +++ b/client/src/hooks/helpers/useBanks.tsx @@ -1,4 +1,4 @@ -import { Position } from "@bibliothecadao/eternum"; +import { ContractAddress, ID, Position } from "@bibliothecadao/eternum"; import { useEntityQuery } from "@dojoengine/react"; import { Has, HasValue, getComponentValue } from "@dojoengine/recs"; import { useDojo } from "../context/DojoContext"; @@ -11,7 +11,7 @@ export const useGetBanks = (onlyMine?: boolean) => { }, } = useDojo(); - const query = onlyMine ? [Has(Bank), HasValue(Owner, { address: BigInt(account.address) })] : [Has(Bank)]; + const query = onlyMine ? [Has(Bank), HasValue(Owner, { address: ContractAddress(account.address) })] : [Has(Bank)]; const entityIds = useEntityQuery(query); return entityIds @@ -24,5 +24,5 @@ export const useGetBanks = (onlyMine?: boolean) => { position: { x: position.x, y: position.y }, }; }) - .filter(Boolean) as { entityId: bigint; position: Position }[]; + .filter(Boolean) as { entityId: ID; position: Position }[]; }; diff --git a/client/src/hooks/helpers/useBuildings.tsx b/client/src/hooks/helpers/useBuildings.tsx index 5adabb83c..7eb582223 100644 --- a/client/src/hooks/helpers/useBuildings.tsx +++ b/client/src/hooks/helpers/useBuildings.tsx @@ -1,4 +1,4 @@ -import { BuildingType } from "@bibliothecadao/eternum"; +import { BuildingType, ID } from "@bibliothecadao/eternum"; import { getComponentValue } from "@dojoengine/recs"; import { getEntityIdFromKeys } from "@dojoengine/utils"; import { uuid } from "@latticexyz/utils"; @@ -15,26 +15,26 @@ export function useBuildings() { } = useDojo(); const optimisticBuilding = ( - entityId: bigint, + entityId: ID, col: number, row: number, buildingType: BuildingType, - resourceType?: number, + resourceType?: ID, ) => { let overrideId = uuid(); - const realmPosition = getComponentValue(Position, getEntityIdFromKeys([entityId])); + const realmPosition = getComponentValue(Position, getEntityIdFromKeys([BigInt(entityId)])); const { x: outercol, y: outerrow } = realmPosition || { x: 0, y: 0 }; const entity = getEntityIdFromKeys([outercol, outerrow, col, row].map((v) => BigInt(v))); Building.addOverride(overrideId, { entity, value: { - outer_col: BigInt(outercol), - outer_row: BigInt(outerrow), - inner_col: BigInt(col), - inner_row: BigInt(row), + outer_col: outercol, + outer_row: outerrow, + inner_col: col, + inner_row: row, category: BuildingType[buildingType], produced_resource_type: resourceType ? resourceType : 0, - bonus_percent: 0n, + bonus_percent: 0, entity_id: entityId, outer_entity_id: entityId, }, @@ -42,41 +42,41 @@ export function useBuildings() { return overrideId; }; - const optimisticDestroy = (entityId: bigint, col: number, row: number) => { + const optimisticDestroy = (entityId: ID, col: number, row: number) => { const overrideId = uuid(); - const realmPosition = getComponentValue(Position, getEntityIdFromKeys([entityId])); + const realmPosition = getComponentValue(Position, getEntityIdFromKeys([BigInt(entityId)])); const { x: outercol, y: outerrow } = realmPosition || { x: 0, y: 0 }; const entity = getEntityIdFromKeys([outercol, outerrow, col, row].map((v) => BigInt(v))); Building.addOverride(overrideId, { entity, value: { - outer_col: BigInt(outercol), - outer_row: BigInt(outerrow), - inner_col: BigInt(col), - inner_row: BigInt(row), + outer_col: outercol, + outer_row: outerrow, + inner_col: col, + inner_row: row, category: "", produced_resource_type: 0, - bonus_percent: 0n, - entity_id: 0n, - outer_entity_id: 0n, + bonus_percent: 0, + entity_id: 0, + outer_entity_id: 0, }, }); return overrideId; }; const placeBuilding = async ( - realmEntityId: bigint, + realmEntityId: ID, col: number, row: number, buildingType: BuildingType, - resourceType?: number, + resourceType?: ID, ) => { // add optimisitc rendering let overrideId = optimisticBuilding(realmEntityId, col, row, buildingType, resourceType); await create_building({ signer: account, - entity_id: realmEntityId as bigint, + entity_id: realmEntityId, building_coord: { x: col.toString(), y: row.toString(), @@ -93,13 +93,13 @@ export function useBuildings() { }); }; - const destroyBuilding = async (realmEntityId: bigint, col: number, row: number) => { + const destroyBuilding = async (realmEntityId: ID, col: number, row: number) => { // add optimisitc rendering let overrideId = optimisticDestroy(realmEntityId, col, row); await destroy_building({ signer: account, - entity_id: realmEntityId as bigint, + entity_id: realmEntityId, building_coord: { x: col.toString(), y: row.toString(), diff --git a/client/src/hooks/helpers/useCaravans.tsx b/client/src/hooks/helpers/useCaravans.tsx index 020059930..477149ca5 100644 --- a/client/src/hooks/helpers/useCaravans.tsx +++ b/client/src/hooks/helpers/useCaravans.tsx @@ -1,3 +1,4 @@ +import { ID } from "@bibliothecadao/eternum"; import { getComponentValue } from "@dojoengine/recs"; import { getEntityIdFromKeys } from "../../ui/utils/utils"; import { useDojo } from "../context/DojoContext"; @@ -9,10 +10,10 @@ export function useCaravan() { }, } = useDojo(); - function calculateDistance(startId: bigint, destinationId: bigint): number | undefined { + function calculateDistance(startId: ID, destinationId: ID): number | undefined { // d = √((x2-x1)² + (y2-y1)²) - let start = getComponentValue(Position, getEntityIdFromKeys([startId])); - let destination = getComponentValue(Position, getEntityIdFromKeys([destinationId])); + let start = getComponentValue(Position, getEntityIdFromKeys([BigInt(startId)])); + let destination = getComponentValue(Position, getEntityIdFromKeys([BigInt(destinationId)])); if (start && destination) { // Calculate the difference in x and y coordinates const deltaX = Math.abs(start.x - destination.x); diff --git a/client/src/hooks/helpers/useContributions.tsx b/client/src/hooks/helpers/useContributions.tsx index 1f31287e0..16e2a2a86 100644 --- a/client/src/hooks/helpers/useContributions.tsx +++ b/client/src/hooks/helpers/useContributions.tsx @@ -1,6 +1,7 @@ -import { useDojo } from "../context/DojoContext"; -import { HasValue, getComponentValue, runQuery } from "@dojoengine/recs"; +import { ContractAddress, ID } from "@bibliothecadao/eternum"; import { useEntityQuery } from "@dojoengine/react"; +import { HasValue, getComponentValue, runQuery } from "@dojoengine/recs"; +import { useDojo } from "../context/DojoContext"; export const useContributions = () => { const { @@ -9,7 +10,7 @@ export const useContributions = () => { }, } = useDojo(); - const getContributions = (hyperstructureEntityId: bigint) => { + const getContributions = (hyperstructureEntityId: ID) => { const contributionsToHyperstructure = Array.from( runQuery([HasValue(Contribution, { hyperstructure_entity_id: hyperstructureEntityId })]), ).map((id) => getComponentValue(Contribution, id)); @@ -17,7 +18,7 @@ export const useContributions = () => { return contributionsToHyperstructure; }; - const getContributionsByPlayerAddress = (playerAddress: bigint, hyperstructureEntityId: bigint) => { + const getContributionsByPlayerAddress = (playerAddress: ContractAddress, hyperstructureEntityId: ID) => { const contributionsToHyperstructure = useEntityQuery([ HasValue(Contribution, { hyperstructure_entity_id: hyperstructureEntityId, player_address: playerAddress }), ]) diff --git a/client/src/hooks/helpers/useEntities.tsx b/client/src/hooks/helpers/useEntities.tsx index 3ea6db543..a64c64f62 100644 --- a/client/src/hooks/helpers/useEntities.tsx +++ b/client/src/hooks/helpers/useEntities.tsx @@ -1,19 +1,18 @@ import { ClientComponents } from "@/dojo/createClientComponents"; import { getRealmNameById } from "@/ui/utils/realms"; import { divideByPrecision, getEntityIdFromKeys, getPosition } from "@/ui/utils/utils"; -import { EntityType } from "@bibliothecadao/eternum"; +import { ContractAddress, EntityType, ID } from "@bibliothecadao/eternum"; import { useEntityQuery } from "@dojoengine/react"; import { ComponentValue, Has, HasValue, NotValue, getComponentValue } from "@dojoengine/recs"; import { shortString } from "starknet"; import { useDojo } from "../context/DojoContext"; import { getResourcesUtils } from "./useResources"; -export interface PlayerStructure { +export type PlayerStructure = ComponentValue & { position: ComponentValue; - name: string | undefined; - entity_id?: bigint | undefined; + name: string; category?: string | undefined; -} +}; export const useEntities = () => { const { @@ -25,9 +24,12 @@ export const useEntities = () => { const { getEntityName } = getEntitiesUtils(); - const playerRealms = useEntityQuery([Has(Realm), HasValue(Owner, { address: BigInt(account.address) })]); - const otherRealms = useEntityQuery([Has(Realm), NotValue(Owner, { address: BigInt(account.address) })]); - const playerStructures = useEntityQuery([Has(Structure), HasValue(Owner, { address: BigInt(account.address) })]); + const playerRealms = useEntityQuery([Has(Realm), HasValue(Owner, { address: ContractAddress(account.address) })]); + const otherRealms = useEntityQuery([Has(Realm), NotValue(Owner, { address: ContractAddress(account.address) })]); + const playerStructures = useEntityQuery([ + Has(Structure), + HasValue(Owner, { address: ContractAddress(account.address) }), + ]); return { playerRealms: () => { @@ -46,6 +48,8 @@ export const useEntities = () => { return playerStructures .map((id) => { const structure = getComponentValue(Structure, id); + if (!structure) return; + const realm = getComponentValue(Realm, id); const position = getComponentValue(Position, id); @@ -55,9 +59,10 @@ export const useEntities = () => { ? getRealmNameById(realm.realm_id) : structureName ? `${structure?.category} ${structureName}` - : structure?.category; + : structure.category || ""; return { ...structure, position: position!, name }; }) + .filter((structure): structure is PlayerStructure => structure !== undefined) .sort((a, b) => (b.category || "").localeCompare(a.category || "")); }, }; @@ -73,18 +78,19 @@ export const getEntitiesUtils = () => { const { getResourcesFromBalance } = getResourcesUtils(); - const getEntityInfo = (entityId: bigint) => { - const arrivalTime = getComponentValue(ArrivalTime, getEntityIdFromKeys([entityId])); - const movable = getComponentValue(Movable, getEntityIdFromKeys([entityId])); - const capacity = getComponentValue(Capacity, getEntityIdFromKeys([entityId])); + const getEntityInfo = (entityId: ID) => { + const entityIdBigInt = BigInt(entityId); + const arrivalTime = getComponentValue(ArrivalTime, getEntityIdFromKeys([entityIdBigInt])); + const movable = getComponentValue(Movable, getEntityIdFromKeys([entityIdBigInt])); + const capacity = getComponentValue(Capacity, getEntityIdFromKeys([entityIdBigInt])); - const entityOwner = getComponentValue(EntityOwner, getEntityIdFromKeys([entityId])); - const owner = getComponentValue(Owner, getEntityIdFromKeys([entityOwner?.entity_owner_id || BigInt("")])); + const entityOwner = getComponentValue(EntityOwner, getEntityIdFromKeys([entityIdBigInt])); + const owner = getComponentValue(Owner, getEntityIdFromKeys([BigInt(entityOwner?.entity_owner_id || 0)])); const name = getEntityName(entityId); const resources = getResourcesFromBalance(entityId); - const army = getComponentValue(Army, getEntityIdFromKeys([entityId])); + const army = getComponentValue(Army, getEntityIdFromKeys([entityIdBigInt])); const rawIntermediateDestination = movable ? { x: movable.intermediate_coord_x, y: movable.intermediate_coord_y } : undefined; @@ -92,10 +98,10 @@ export const getEntitiesUtils = () => { ? { x: rawIntermediateDestination.x, y: rawIntermediateDestination.y } : undefined; - const position = getComponentValue(Position, getEntityIdFromKeys([entityId])); + const position = getComponentValue(Position, getEntityIdFromKeys([entityIdBigInt])); const homePosition = entityOwner - ? getComponentValue(Position, getEntityIdFromKeys([BigInt(entityOwner?.entity_owner_id || BigInt(""))])) + ? getComponentValue(Position, getEntityIdFromKeys([BigInt(entityOwner?.entity_owner_id || 0)])) : undefined; return { @@ -107,7 +113,7 @@ export const getEntitiesUtils = () => { position: position ? { x: position.x, y: position.y } : undefined, homePosition: homePosition ? { x: homePosition.x, y: homePosition.y } : undefined, owner: owner?.address, - isMine: BigInt(owner?.address || "") === BigInt(account.address), + isMine: ContractAddress(owner?.address || 0n) === ContractAddress(account.address), isRoundTrip: movable?.round_trip || false, resources, entityType: army ? EntityType.TROOP : EntityType.DONKEY, @@ -115,12 +121,12 @@ export const getEntitiesUtils = () => { }; }; - const getEntityName = (entityId: bigint) => { - const entityName = getComponentValue(EntityName, getEntityIdFromKeys([entityId])); + const getEntityName = (entityId: ID) => { + const entityName = getComponentValue(EntityName, getEntityIdFromKeys([BigInt(entityId)])); return entityName ? shortString.decodeShortString(entityName.name.toString()) : entityId.toString(); }; - const getAddressNameFromEntity = (entityId: bigint) => { + const getAddressNameFromEntity = (entityId: ID) => { const address = getPlayerAddressFromEntity(entityId); if (!address) return; @@ -129,10 +135,10 @@ export const getEntitiesUtils = () => { return addressName ? shortString.decodeShortString(addressName.name.toString()) : undefined; }; - const getPlayerAddressFromEntity = (entityId: bigint) => { - const entityOwner = getComponentValue(EntityOwner, getEntityIdFromKeys([entityId])); + const getPlayerAddressFromEntity = (entityId: ID) => { + const entityOwner = getComponentValue(EntityOwner, getEntityIdFromKeys([BigInt(entityId)])); return entityOwner?.entity_owner_id - ? getComponentValue(Owner, getEntityIdFromKeys([entityOwner.entity_owner_id]))?.address + ? getComponentValue(Owner, getEntityIdFromKeys([BigInt(entityOwner.entity_owner_id)]))?.address : undefined; }; diff --git a/client/src/hooks/helpers/useExplore.tsx b/client/src/hooks/helpers/useExplore.tsx index 8f9ab0ee7..c0496760a 100644 --- a/client/src/hooks/helpers/useExplore.tsx +++ b/client/src/hooks/helpers/useExplore.tsx @@ -2,6 +2,7 @@ import { useExploredHexesStore } from "@/ui/components/worldmap/hexagon/WorldHex import { FELT_CENTER } from "@/ui/config"; import { EternumGlobalConfig, + ID, Position, Resource, neighborOffsetsEven, @@ -18,7 +19,7 @@ import useRealmStore from "../store/useRealmStore"; import { useStamina } from "./useStamina"; interface ExploreHexProps { - explorerId: bigint | undefined; + explorerId: ID | undefined; direction: number | undefined; path: Position[]; currentArmiesTick: number; @@ -35,6 +36,7 @@ export function useExplore() { }, account: { account }, } = useDojo(); + const realmEntityIds = useRealmStore((state) => state.realmEntityIds); const setExploredHexes = useExploredHexesStore((state) => state.setExploredHexes); const { optimisticStaminaUpdate } = useStamina(); @@ -64,7 +66,7 @@ export function useExplore() { return explored; }; - const useFoundResources = (entityId: bigint | undefined) => { + const useFoundResources = (entityId: ID | undefined) => { const [foundResources, setFoundResources] = useState(); const subscriptionRef = useRef(); @@ -119,10 +121,10 @@ export function useExplore() { } }; - const optimisticExplore = (entityId: bigint, col: number, row: number, currentArmiesTick: number) => { + const optimisticExplore = (entityId: ID, col: number, row: number, currentArmiesTick: number) => { let overrideId = uuid(); - const entity = getEntityIdFromKeys([entityId]); + const entity = getEntityIdFromKeys([BigInt(entityId)]); optimisticStaminaUpdate(overrideId, entityId, EternumGlobalConfig.stamina.exploreCost, currentArmiesTick); diff --git a/client/src/hooks/helpers/useGuilds.tsx b/client/src/hooks/helpers/useGuilds.tsx index 16d081243..5be93b60b 100644 --- a/client/src/hooks/helpers/useGuilds.tsx +++ b/client/src/hooks/helpers/useGuilds.tsx @@ -1,4 +1,5 @@ import { ClientComponents } from "@/dojo/createClientComponents"; +import { ContractAddress, ID } from "@bibliothecadao/eternum"; import { useEntityQuery } from "@dojoengine/react"; import { Component, @@ -44,7 +45,6 @@ export const useGuilds = () => { setup: { components: { Guild, GuildMember, GuildWhitelist, Owner }, }, - account: { account }, } = useDojo(); const { getEntityName } = getEntitiesUtils(); @@ -53,7 +53,7 @@ export const useGuilds = () => { const guildPointsLeaderboard = useLeaderBoardStore((state) => state.guildPointsLeaderboard); const getGuildMembers = useMemo( - () => (guildEntityId: bigint) => { + () => (guildEntityId: ID) => { const guildMembers = useEntityQuery([HasValue(GuildMember, { guild_entity_id: guildEntityId })]); return { guildMembers: formatGuildMembers(guildMembers, GuildMember, getAddressName), @@ -64,7 +64,6 @@ export const useGuilds = () => { const getGuilds = useMemo( () => () => { - // TODO: CONSTANT 0n const guilds = useEntityQuery([Has(Guild), NotValue(Guild, { member_count: 0 })]); return { guilds: formatGuilds(guilds, Guild, getEntityName, guildPointsLeaderboard), @@ -74,10 +73,9 @@ export const useGuilds = () => { ); const getGuildWhitelist = useMemo( - () => (guildEntityId: bigint) => { + () => (guildEntityId: ID) => { const whitelist = useEntityQuery([ - // TODO : CONSTANT 1n - HasValue(GuildWhitelist, { guild_entity_id: guildEntityId, is_whitelisted: 1n }), + HasValue(GuildWhitelist, { guild_entity_id: guildEntityId, is_whitelisted: true }), ]); return { whitelist: formatGuildWhitelist(whitelist, GuildWhitelist, getAddressName), @@ -87,9 +85,8 @@ export const useGuilds = () => { ); const getAddressWhitelist = useMemo( - () => (address: bigint) => { - // TODO : CONSTANT 1n - const addressWhitelist = useEntityQuery([HasValue(GuildWhitelist, { address, is_whitelisted: 1n })]); + () => (address: ContractAddress) => { + const addressWhitelist = useEntityQuery([HasValue(GuildWhitelist, { address, is_whitelisted: true })]); return { addressWhitelist: formatAddressWhitelist(addressWhitelist, GuildWhitelist, getEntityName), }; @@ -98,7 +95,7 @@ export const useGuilds = () => { ); const getGuildOwner = useMemo( - () => (guildEntityId: bigint) => { + () => (guildEntityId: ID) => { const owner = Array.from(runQuery([HasValue(Owner, { entity_id: guildEntityId })])).map((id) => getComponentValue(Owner, id), )[0]; @@ -108,18 +105,18 @@ export const useGuilds = () => { ); const getAddressGuild = useMemo( - () => (accountAddress: string) => { - const userGuildEntityId = Array.from(runQuery([HasValue(GuildMember, { address: BigInt(accountAddress) })])).map( - (id) => getComponentValue(GuildMember, id), + () => (accountAddress: ContractAddress) => { + const userGuildEntityId = Array.from(runQuery([HasValue(GuildMember, { address: accountAddress })])).map((id) => + getComponentValue(GuildMember, id), )[0]?.guild_entity_id; const guildName = userGuildEntityId ? getEntityName(userGuildEntityId) : undefined; const owner = Array.from( - runQuery([HasValue(Owner, { address: BigInt(accountAddress), entity_id: userGuildEntityId })]), + runQuery([HasValue(Owner, { address: accountAddress, entity_id: userGuildEntityId })]), ).map((id) => getComponentValue(Owner, id))[0]; - const isOwner = owner ? (owner.address === BigInt(account.address) ? true : false) : false; + const isOwner = owner ? (owner.address === accountAddress ? true : false) : false; const memberCount = Array.from(runQuery([HasValue(Guild, { entity_id: userGuildEntityId })])).map((id) => getComponentValue(Guild, id), @@ -141,7 +138,7 @@ export const useGuilds = () => { const formatGuilds = ( guilds: Entity[], Guild: Component, - getEntityName: (entityId: bigint) => string, + getEntityName: (entityId: ID) => string, guildPointsLeaderboard: GuildPointsLeaderboardInterface[], ): GuildAndName[] => { return guilds @@ -165,13 +162,13 @@ const formatGuilds = ( const formatGuildMembers = ( guildMembers: Entity[], GuildMember: Component, - getAddressName: (address: string) => string | undefined, + getAddressName: (address: ContractAddress) => string | undefined, ): GuildMemberAndName[] => { return guildMembers .map((entity) => { const guildMember = getComponentValue(GuildMember, entity); if (!guildMember) return; - const addressName = getAddressName(String(guildMember.address)); + const addressName = getAddressName(guildMember.address); const playerAddress = "0x" + guildMember.address.toString(16); return { guildMember, @@ -185,14 +182,14 @@ const formatGuildMembers = ( const formatGuildWhitelist = ( whitelist: Entity[], GuildWhitelist: Component, - getAddressName: (address: string) => string | undefined, + getAddressName: (address: ContractAddress) => string | undefined, ): GuildWhitelistAndName[] => { return whitelist .map((entity) => { const guildWhitelist = getComponentValue(GuildWhitelist, entity); if (!guildWhitelist) return; - const addressName = getAddressName(String(guildWhitelist.address)); + const addressName = getAddressName(guildWhitelist.address); const playerAddress = "0x" + guildWhitelist.address.toString(16); return { guildWhitelist, @@ -206,14 +203,14 @@ const formatGuildWhitelist = ( const formatAddressWhitelist = ( addressWhitelist: Entity[], GuildWhitelist: Component, - getEntityName: (entityId: bigint) => string, + getEntityName: (entityId: ID) => string, ): AddressWhitelistAndName[] => { return addressWhitelist .map((entity) => { const addressWhitelist = getComponentValue(GuildWhitelist, entity); if (!addressWhitelist) return; - const name = getEntityName(BigInt(addressWhitelist.guild_entity_id)); + const name = getEntityName(addressWhitelist.guild_entity_id); return { addressWhitelist, name, diff --git a/client/src/hooks/helpers/useHyperstructures.tsx b/client/src/hooks/helpers/useHyperstructures.tsx index 1b3737128..b529ff3ce 100644 --- a/client/src/hooks/helpers/useHyperstructures.tsx +++ b/client/src/hooks/helpers/useHyperstructures.tsx @@ -1,5 +1,5 @@ import { ClientComponents } from "@/dojo/createClientComponents"; -import { EternumGlobalConfig, HYPERSTRUCTURE_TOTAL_COSTS_SCALED } from "@bibliothecadao/eternum"; +import { EternumGlobalConfig, HYPERSTRUCTURE_TOTAL_COSTS_SCALED, ID, ResourcesIds } from "@bibliothecadao/eternum"; import { useEntityQuery } from "@dojoengine/react"; import { Component, ComponentValue, Entity, Has, HasValue, getComponentValue, runQuery } from "@dojoengine/recs"; import { toInteger } from "lodash"; @@ -7,23 +7,15 @@ import { shortString } from "starknet"; import { useDojo } from "../context/DojoContext"; import { ResourceMultipliers, TOTAL_CONTRIBUTABLE_AMOUNT } from "../store/useLeaderBoardStore"; -export type Hyperstructure = ComponentValue & { - entityIdPoseidon: Entity; - name: string; - progress: ComponentValue; - contribution: ComponentValue; - position: ComponentValue; -}; - export type ProgressWithPercentage = { percentage: number; costNeeded: number; - hyperstructure_entity_id: bigint; - resource_type: number; + hyperstructure_entity_id: ID; + resource_type: ResourcesIds; amount: number; }; -export type Progress = { +type Progress = { percentage: number; progresses: ProgressWithPercentage[]; }; @@ -40,12 +32,11 @@ export const useHyperstructures = () => { const hyperstructure = getComponentValue(Structure, hyperstructureEntityId); const position = getComponentValue(Position, hyperstructureEntityId); const contributions = getContributions(hyperstructure!.entity_id, Contribution); - const owner = `0x${getComponentValue( - Owner, - runQuery([Has(Owner), HasValue(Owner, { entity_id: hyperstructure!.entity_id })]) - .values() - .next().value, - )?.address.toString(16)}`; + const ownerEntityIds = runQuery([Has(Owner), HasValue(Owner, { entity_id: hyperstructure!.entity_id })]) + .values() + .next().value; + + const owner = `0x${getComponentValue(Owner, ownerEntityIds || ("" as Entity))?.address.toString(16)}`; const entityName = getComponentValue(EntityName, hyperstructureEntityId); return { ...hyperstructure, @@ -60,7 +51,7 @@ export const useHyperstructures = () => { }, ); - const useProgress = (hyperstructureEntityId: bigint): Progress => { + const useProgress = (hyperstructureEntityId: ID): Progress => { let progressQueryResult = useEntityQuery([ Has(Progress), HasValue(Progress, { hyperstructure_entity_id: hyperstructureEntityId }), @@ -72,7 +63,7 @@ export const useHyperstructures = () => { return { percentage: toInteger(percentage * 100), progresses: allProgresses }; }; - const getHyperstructureProgress = (hyperstructureEntityId: bigint) => { + const getHyperstructureProgress = (hyperstructureEntityId: ID) => { let progressQueryResult = runQuery([ Has(Progress), HasValue(Progress, { hyperstructure_entity_id: hyperstructureEntityId }), @@ -87,7 +78,7 @@ export const useHyperstructures = () => { return { hyperstructures, useProgress, getHyperstructureProgress }; }; -const getContributions = (hyperstructureEntityId: bigint, Contribution: Component) => { +const getContributions = (hyperstructureEntityId: ID, Contribution: Component) => { const contributions = runQuery([ Has(Contribution), HasValue(Contribution, { hyperstructure_entity_id: hyperstructureEntityId }), @@ -97,8 +88,7 @@ const getContributions = (hyperstructureEntityId: bigint, Contribution: Componen const getAllProgressesAndTotalPercentage = ( progresses: (ComponentValue | undefined)[], - - hyperstructureEntityId: bigint, + hyperstructureEntityId: ID, ) => { let percentage = 0; const allProgresses = HYPERSTRUCTURE_TOTAL_COSTS_SCALED.map(({ resource, amount: resourceCost }) => { @@ -106,10 +96,12 @@ const getAllProgressesAndTotalPercentage = ( let progress = { hyperstructure_entity_id: hyperstructureEntityId, resource_type: resource, - amount: !foundProgress ? 0 : foundProgress.amount / EternumGlobalConfig.resources.resourcePrecision, + amount: !foundProgress ? 0 : Number(foundProgress.amount) / EternumGlobalConfig.resources.resourcePrecision, percentage: !foundProgress ? 0 - : Math.floor((foundProgress.amount / EternumGlobalConfig.resources.resourcePrecision / resourceCost!) * 100), + : Math.floor( + (Number(foundProgress.amount) / EternumGlobalConfig.resources.resourcePrecision / resourceCost!) * 100, + ), costNeeded: resourceCost, }; percentage += diff --git a/client/src/hooks/helpers/useQuests.tsx b/client/src/hooks/helpers/useQuests.tsx index 18dab39dd..d7167f414 100644 --- a/client/src/hooks/helpers/useQuests.tsx +++ b/client/src/hooks/helpers/useQuests.tsx @@ -1,14 +1,14 @@ -import { useCallback, useEffect, useMemo, useState } from "react"; -import { BuildingType, QuestType, StructureType } from "@bibliothecadao/eternum"; -import { useDojo } from "../context/DojoContext"; +import { getPillageEvents } from "@/dojo/events/pillageEventQueries"; +import { QuestId, questDetails } from "@/ui/components/quest/questDetails"; +import { BuildingType, ContractAddress, ID, QuestType, StructureType } from "@bibliothecadao/eternum"; import { useEntityQuery } from "@dojoengine/react"; import { HasValue, getComponentValue, runQuery } from "@dojoengine/recs"; import { getEntityIdFromKeys } from "@dojoengine/utils"; -import { useEntities } from "./useEntities"; +import { useCallback, useEffect, useMemo, useState } from "react"; +import { useDojo } from "../context/DojoContext"; import { ArmyInfo, useArmiesByEntityOwner } from "./useArmies"; +import { useEntities } from "./useEntities"; import { useGetMyOffers } from "./useTrade"; -import { getPillageEvents } from "@/dojo/events/pillageEventQueries"; -import { QuestId, questDetails } from "@/ui/components/quest/questDetails"; export interface Quest { id: QuestId; @@ -76,11 +76,11 @@ const useQuestDependencies = () => { const realm = useMemo(() => playerRealms()[0], [playerRealms]); const realmEntityId = useMemo(() => realm?.entity_id, [realm]); - const entityUpdate = useEntityQuery([HasValue(EntityOwner, { entity_owner_id: BigInt(realmEntityId || "0") })]); + const entityUpdate = useEntityQuery([HasValue(EntityOwner, { entity_owner_id: realmEntityId || 0 })]); const buildingQuantities = useBuildingQuantities(realmEntityId); - const { entityArmies } = useArmiesByEntityOwner({ entity_owner_entity_id: realmEntityId || BigInt("0") }); + const { entityArmies } = useArmiesByEntityOwner({ entity_owner_entity_id: realmEntityId || 0 }); const orders = useGetMyOffers(); const hasTroops = useMemo(() => armyHasTroops(entityArmies), [entityArmies]); @@ -90,7 +90,7 @@ const useQuestDependencies = () => { useEffect(() => { const fetchPillageHistory = async () => { - const eventsLength = await getPillageEvents(BigInt(realmEntityId ?? "0")); + const eventsLength = await getPillageEvents(realmEntityId || 0); setPillageHistoryLength(eventsLength); }; fetchPillageHistory(); @@ -117,7 +117,7 @@ const useQuestDependencies = () => { ); const hyperstructureContributions = useMemo( - () => runQuery([HasValue(Contribution, { player_address: BigInt(account.address) })]).size, + () => runQuery([HasValue(Contribution, { player_address: ContractAddress(account.address) })]).size, [realmEntityId], ); @@ -236,15 +236,13 @@ export const useQuestClaimStatus = () => { const realm = useMemo(() => playerRealms()[0], [playerRealms]); const realmEntityId = useMemo(() => realm?.entity_id, [realm]); - const prizeUpdate = useEntityQuery([ - HasValue(HasClaimedStartingResources, { entity_id: BigInt(realmEntityId || "0") }), - ]); + const prizeUpdate = useEntityQuery([HasValue(HasClaimedStartingResources, { entity_id: realmEntityId || 0 })]); const checkPrizesClaimed = (prizes: Prize[]) => { return prizes.every((prize) => { const value = getComponentValue( HasClaimedStartingResources, - getEntityIdFromKeys([BigInt(realmEntityId || "0"), BigInt(prize.id)]), + getEntityIdFromKeys([BigInt(realmEntityId || 0), BigInt(prize.id)]), ); return value?.claimed; }); @@ -274,15 +272,15 @@ export const useUnclaimedQuestsCount = () => { return { unclaimedQuestsCount }; }; -const useBuildingQuantities = (realmEntityId: bigint | undefined) => { +const useBuildingQuantities = (realmEntityId: ID | undefined) => { const { setup: { components: { BuildingQuantityv2, EntityOwner }, }, } = useDojo(); - const entityUpdate = useEntityQuery([HasValue(EntityOwner, { entity_owner_id: BigInt(realmEntityId || "0") })]); + const entityUpdate = useEntityQuery([HasValue(EntityOwner, { entity_owner_id: realmEntityId || 0 })]); const getBuildingQuantity = (buildingType: BuildingType) => - getComponentValue(BuildingQuantityv2, getEntityIdFromKeys([BigInt(realmEntityId || "0"), BigInt(buildingType)])) + getComponentValue(BuildingQuantityv2, getEntityIdFromKeys([BigInt(realmEntityId || 0), BigInt(buildingType)])) ?.value || 0; return useMemo( diff --git a/client/src/hooks/helpers/useRealm.tsx b/client/src/hooks/helpers/useRealm.tsx index a0f687905..9df49cf59 100644 --- a/client/src/hooks/helpers/useRealm.tsx +++ b/client/src/hooks/helpers/useRealm.tsx @@ -1,6 +1,14 @@ -import { BASE_POPULATION_CAPACITY, RealmInterface, getOrderName } from "@bibliothecadao/eternum"; +import { + BASE_POPULATION_CAPACITY, + ContractAddress, + ID, + RealmInterface, + ResourcesIds, + getOrderName, + getQuestResources as getStartingResources, +} from "@bibliothecadao/eternum"; import { useEntityQuery } from "@dojoengine/react"; -import { Has, HasValue, getComponentValue, runQuery } from "@dojoengine/recs"; +import { Entity, Has, HasValue, getComponentValue, runQuery } from "@dojoengine/recs"; import { useMemo } from "react"; import { shortString } from "starknet"; import realmIdsByOrder from "../../data/realmids_by_order.json"; @@ -8,12 +16,11 @@ import { unpackResources } from "../../ui/utils/packedData"; import { getRealm, getRealmNameById } from "../../ui/utils/realms"; import { getEntityIdFromKeys, getPosition } from "../../ui/utils/utils"; import { useDojo } from "../context/DojoContext"; -import { getQuestResources as getStartingResources } from "@bibliothecadao/eternum"; import useRealmStore from "../store/useRealmStore"; -export type RealmExtended = RealmInterface & { - entity_id: bigint; - resources: number[]; +type RealmExtended = RealmInterface & { + entity_id: ID; + resources: ResourcesIds[]; }; export function useRealm() { @@ -30,12 +37,12 @@ export function useRealm() { return getStartingResources(resourcesProduced); }; - const getEntityOwner = (entityId: bigint) => { - const entityOwner = getComponentValue(EntityOwner, getEntityIdFromKeys([entityId])); + const getEntityOwner = (entityId: ID) => { + const entityOwner = getComponentValue(EntityOwner, getEntityIdFromKeys([BigInt(entityId)])); return entityOwner?.entity_owner_id; }; - const isRealmIdSettled = (realmId: bigint) => { + const isRealmIdSettled = (realmId: ID) => { const entityIds = runQuery([HasValue(Realm, { realm_id: realmId })]); return entityIds.size > 0; }; @@ -51,13 +58,13 @@ export function useRealm() { let latestRealmIdFromOrder = 0; if (realmEntityIds.length > 0) { const realmEntityId = realmEntityIds.sort((a, b) => Number(b) - Number(a))[0]; - const latestRealmFromOrder = getComponentValue(Realm, getEntityIdFromKeys([realmEntityId])); + const latestRealmFromOrder = getComponentValue(Realm, getEntityIdFromKeys([BigInt(realmEntityId)])); if (latestRealmFromOrder) { latestRealmIdFromOrder = Number(latestRealmFromOrder.realm_id); } } - const orderRealmIds = (realmIdsByOrder as { [key: string]: number[] })[orderName]; + const orderRealmIds = (realmIdsByOrder as { [key: string]: ID[] })[orderName]; let nextRealmIdFromOrder = 0; const maxIterations = orderRealmIds.length; @@ -71,11 +78,11 @@ export function useRealm() { nextRealmIdFromOrder = orderRealmIds[latestIndex + 1]; } - const position = getPosition(BigInt(nextRealmIdFromOrder)); + const position = getPosition(nextRealmIdFromOrder); // check if there is a structure on position, if no structure we can keep this realm Id if (Array.from(runQuery([HasValue(Position, { x: position.x, y: position.y }), Has(Structure)])).length === 0) { - return BigInt(nextRealmIdFromOrder); + return nextRealmIdFromOrder; } else { latestRealmIdFromOrder = nextRealmIdFromOrder; } @@ -84,51 +91,49 @@ export function useRealm() { throw new Error(`Could not find an unoccupied realm ID for order ${orderName} after ${maxIterations} attempts`); }; - const getRealmEntityIdFromRealmId = (realmId: bigint): bigint | undefined => { + const getRealmEntityIdFromRealmId = (realmId: ID): ID | undefined => { const realmEntityIds = runQuery([HasValue(Realm, { realm_id: realmId })]); if (realmEntityIds.size > 0) { - const realm = getComponentValue(Realm, realmEntityIds.values().next().value); + const realm = getComponentValue(Realm, realmEntityIds.values().next().value || ("" as Entity)); return realm!.entity_id; } }; - const getRealmIdFromRealmEntityId = (realmEntityId: bigint) => { - const realm = getComponentValue(Realm, getEntityIdFromKeys([realmEntityId])); + const getRealmIdFromRealmEntityId = (realmEntityId: ID) => { + const realm = getComponentValue(Realm, getEntityIdFromKeys([BigInt(realmEntityId)])); return realm?.realm_id; }; - const getRealmIdForOrderAfter = (order: number, realmId: bigint) => { + const getRealmIdForOrderAfter = (order: number, realmId: ID): ID => { const orderName = getOrderName(order); - const orderRealmIds = (realmIdsByOrder as { [key: string]: number[] })[orderName]; - const latestIndex = orderRealmIds.indexOf(Number(realmId)); + const orderRealmIds = (realmIdsByOrder as { [key: string]: ID[] })[orderName]; + const latestIndex = orderRealmIds.indexOf(realmId); if (latestIndex === -1 || latestIndex === orderRealmIds.length - 1) { - return BigInt(orderRealmIds[0]); + return orderRealmIds[0]; } else { - return BigInt(orderRealmIds[latestIndex + 1]); + return orderRealmIds[latestIndex + 1]; } }; - const getAddressName = (address: string) => { - const addressName = getComponentValue(AddressName, getEntityIdFromKeys([BigInt(address)])); + const getAddressName = (address: ContractAddress) => { + const addressName = getComponentValue(AddressName, getEntityIdFromKeys([address])); return addressName ? shortString.decodeShortString(addressName.name.toString()) : undefined; }; - const getAddressOrder = (address: string) => { - const ownedRealms = runQuery([Has(Realm), HasValue(Owner, { address: BigInt(address) })]); + const getAddressOrder = (address: ContractAddress) => { + const ownedRealms = runQuery([Has(Realm), HasValue(Owner, { address })]); if (ownedRealms.size > 0) { - const realm = getComponentValue(Realm, ownedRealms.values().next().value); + const realm = getComponentValue(Realm, ownedRealms.values().next().value || ("" as Entity)); return realm?.order; } }; - const getRealmAddressName = (realmEntityId: bigint) => { + const getRealmAddressName = (realmEntityId: ID) => { const owner = getComponentValue(Owner, getEntityIdFromKeys([BigInt(realmEntityId)])); - const addressName = owner - ? getComponentValue(AddressName, getEntityIdFromKeys([BigInt(owner.address)])) - : undefined; + const addressName = owner ? getComponentValue(AddressName, getEntityIdFromKeys([owner.address])) : undefined; if (addressName) { return shortString.decodeShortString(String(addressName.name)); @@ -145,8 +150,8 @@ export function useRealm() { return realmEntityIds.length === 1 ? realmEntityIds[0] : undefined; }; - const isEntityIdRealm = (entityId: bigint) => { - const realm = getComponentValue(Realm, getEntityIdFromKeys([entityId])); + const isEntityIdRealm = (entityId: ID) => { + const realm = getComponentValue(Realm, getEntityIdFromKeys([BigInt(entityId)])); return realm ? true : false; }; @@ -166,7 +171,7 @@ export function useRealm() { }; } -export function useGetRealm(realmEntityId: bigint | undefined) { +export function useGetRealm(realmEntityId: ID | undefined) { const { setup: { components: { Realm, Position, Owner, Population }, @@ -177,7 +182,7 @@ export function useGetRealm(realmEntityId: bigint | undefined) { const realm = useMemo((): any => { if (realmEntityId !== undefined) { - let entityId = getEntityIdFromKeys([realmEntityId]); + let entityId = getEntityIdFromKeys([BigInt(realmEntityId)]); const realm = getComponentValue(Realm, entityId); const owner = getComponentValue(Owner, entityId); const position = getComponentValue(Position, entityId); @@ -247,7 +252,7 @@ export function useGetRealms(): RealmExtended[] { if (!realmData) return undefined; let name = realmData.name; let owner = getComponentValue(Owner, entityId); - let resources = unpackResources(BigInt(realm.resource_types_packed), realm.resource_types_count); + let resources = unpackResources(realm.resource_types_packed, realm.resource_types_count); if (name) { return { diff --git a/client/src/hooks/helpers/useResources.tsx b/client/src/hooks/helpers/useResources.tsx index 6ce23896f..29d05ac9d 100644 --- a/client/src/hooks/helpers/useResources.tsx +++ b/client/src/hooks/helpers/useResources.tsx @@ -1,4 +1,4 @@ -import { Position, ResourcesIds, resources, type Resource } from "@bibliothecadao/eternum"; +import { ContractAddress, ID, Position, ResourcesIds, resources, type Resource } from "@bibliothecadao/eternum"; import { useComponentValue, useEntityQuery } from "@dojoengine/react"; import { Has, HasValue, Not, NotValue, getComponentValue, runQuery, type Entity } from "@dojoengine/recs"; import { useEffect, useMemo, useState } from "react"; @@ -14,15 +14,15 @@ export function getResourcesUtils() { }, } = useDojo(); - const getResourcesFromBalance = (entityId: bigint): Resource[] => { + const getResourcesFromBalance = (entityId: ID): Resource[] => { // todo: switch back to items_count when working - const ownedResources = getComponentValue(OwnedResourcesTracker, getEntityIdFromKeys([entityId])); + const ownedResources = getComponentValue(OwnedResourcesTracker, getEntityIdFromKeys([BigInt(entityId)])); if (!ownedResources) return []; // const resourceIds = getResourceIdsFromPackedNumber(ownedResources.resource_types); const resourceIds = resources.map((r) => r.id); return resourceIds .map((id) => { - const resource = getComponentValue(Resource, getEntityIdFromKeys([entityId, BigInt(id)])); + const resource = getComponentValue(Resource, getEntityIdFromKeys([BigInt(entityId), BigInt(id)])); return { resourceId: id, amount: Number(resource?.balance) || 0 }; }) .filter((r) => r.amount > 0); @@ -40,16 +40,16 @@ export function getResourcesUtils() { }; const getRealmsWithSpecificResource = ( - resourceId: number, + resourceId: ResourcesIds, minAmount: number, - ): Array<{ realmEntityId: bigint; realmId: bigint; amount: number }> => { + ): Array<{ realmEntityId: ID; realmId: ID; amount: number }> => { const allRealms = Array.from(runQuery([Has(Realm)])); const realmsWithResource = allRealms .map((id: Entity) => { const realm = getComponentValue(Realm, id); const resource = realm - ? getComponentValue(Resource, getEntityIdFromKeys([realm?.entity_id, BigInt(resourceId)])) + ? getComponentValue(Resource, getEntityIdFromKeys([BigInt(realm?.entity_id), BigInt(resourceId)])) : undefined; if (resource && resource.balance > minAmount) { @@ -60,7 +60,7 @@ export function getResourcesUtils() { }; } }) - .filter(Boolean) as Array<{ realmEntityId: bigint; realmId: bigint; amount: number }>; + .filter(Boolean) as Array<{ realmEntityId: ID; realmId: ID; amount: number }>; return realmsWithResource; }; @@ -92,29 +92,29 @@ export const useArrivalsWithResources = () => { type ArrivalInfo = { id: Entity; - entityId: bigint; - arrivesAt: number; + entityId: ID; + arrivesAt: bigint; isOwner: boolean; }; return atPositionWithInventory .map((id) => { const entityOwner = getComponentValue(EntityOwner, id); - const owner = getComponentValue(Owner, getEntityIdFromKeys([entityOwner?.entity_owner_id || BigInt(0)])); + const owner = getComponentValue(Owner, getEntityIdFromKeys([BigInt(entityOwner?.entity_owner_id || 0)])); const arrivalTime = getComponentValue(ArrivalTime, id); const position = getComponentValue(Position, id); return { id, - entityId: position?.entity_id || BigInt(""), - arrivesAt: Number(arrivalTime?.arrives_at || 0), - isOwner: BigInt(owner?.address || "") === BigInt(account.address), + entityId: position?.entity_id || 0, + arrivesAt: arrivalTime?.arrives_at || 0n, + isOwner: ContractAddress(owner?.address || 0n) === ContractAddress(account.address), }; }) .filter((val: ArrivalInfo | undefined): val is ArrivalInfo => val !== undefined) .filter(({ isOwner, arrivesAt }) => isOwner && arrivesAt <= currentTime) - .sort((a, b) => a.arrivesAt - b.arrivesAt) + .sort((a, b) => Number(a.arrivesAt) - Number(b.arrivesAt)) .map(({ entityId }) => entityId) - .filter((entityId) => entityId !== BigInt("")); + .filter((entityId) => entityId !== 0); }, [atPositionWithInventory, account.address]); return { @@ -129,21 +129,21 @@ export function getResourceBalance() { }, } = useDojo(); - const getFoodResources = (entityId: bigint): Resource[] => { + const getFoodResources = (entityId: ID): Resource[] => { const currentDefaultTick = useBlockchainStore.getState().currentDefaultTick; const wheatBalance = new ProductionManager( Production, Resource, BuildingQuantityv2, entityId, - BigInt(ResourcesIds.Wheat), + ResourcesIds.Wheat, ).balance(currentDefaultTick); const fishBalance = new ProductionManager( Production, Resource, BuildingQuantityv2, entityId, - BigInt(ResourcesIds.Fish), + ResourcesIds.Fish, ).balance(currentDefaultTick); return [ @@ -152,47 +152,29 @@ export function getResourceBalance() { ]; }; - const getResourceProductionInfo = (entityId: bigint, resourceId: number) => { - const productionManager = new ProductionManager( - Production, - Resource, - BuildingQuantityv2, - entityId, - BigInt(resourceId), - ); + const getResourceProductionInfo = (entityId: ID, resourceId: ResourcesIds) => { + const productionManager = new ProductionManager(Production, Resource, BuildingQuantityv2, entityId, resourceId); return productionManager.getProduction(); }; - const getBalance = (entityId: bigint, resourceId: number) => { + const getBalance = (entityId: ID, resourceId: ResourcesIds) => { const currentDefaultTick = useBlockchainStore.getState().currentDefaultTick; - const productionManager = new ProductionManager( - Production, - Resource, - BuildingQuantityv2, - entityId, - BigInt(resourceId), - ); + const productionManager = new ProductionManager(Production, Resource, BuildingQuantityv2, entityId, resourceId); return { balance: productionManager.balance(currentDefaultTick), resourceId }; }; - const getResourcesBalance = (entityId: bigint) => { + const getResourcesBalance = (entityId: ID) => { const detachedResourceEntityIds = runQuery([HasValue(DetachedResource, { entity_id: entityId })]); return Array.from(detachedResourceEntityIds).map((entityId) => getComponentValue(DetachedResource, entityId)); }; // We should deprecate this hook and use getBalance instead - too many useEffects - const useBalance = (entityId: bigint, resourceId: number) => { + const useBalance = (entityId: ID, resourceId: ResourcesIds) => { const currentDefaultTick = useBlockchainStore((state) => state.currentDefaultTick); const [resourceBalance, setResourceBalance] = useState({ amount: 0, resourceId }); useEffect(() => { - const productionManager = new ProductionManager( - Production, - Resource, - BuildingQuantityv2, - entityId, - BigInt(resourceId), - ); + const productionManager = new ProductionManager(Production, Resource, BuildingQuantityv2, entityId, resourceId); setResourceBalance({ amount: productionManager.balance(currentDefaultTick), resourceId }); }, []); @@ -208,17 +190,17 @@ export function getResourceBalance() { }; } -export const useProductionManager = (entityId: bigint, resourceId: number) => { +export const useProductionManager = (entityId: ID, resourceId: ResourcesIds) => { const { setup: { components: { Resource, Production, BuildingQuantityv2 }, }, } = useDojo(); - const production = useComponentValue(Production, getEntityIdFromKeys([entityId, BigInt(resourceId)])); + const production = useComponentValue(Production, getEntityIdFromKeys([BigInt(entityId), BigInt(resourceId)])); const productionManager = useMemo(() => { - return new ProductionManager(Production, Resource, BuildingQuantityv2, entityId, BigInt(resourceId)); + return new ProductionManager(Production, Resource, BuildingQuantityv2, entityId, resourceId); }, [Production, Resource, entityId, resourceId, production]); return productionManager; @@ -232,7 +214,7 @@ export function useOwnedEntitiesOnPosition() { }, } = useDojo(); - const getOwnedEntitiesOnPosition = (address: bigint, position: Position) => { + const getOwnedEntitiesOnPosition = (address: ContractAddress, position: Position) => { const { x, y } = position; const entities = runQuery([ @@ -251,11 +233,11 @@ export function useOwnedEntitiesOnPosition() { if (!position) return; return position?.entity_id; }) - .filter(Boolean) as bigint[]; + .filter(Boolean) as ID[]; }; - const getOwnedEntityOnPosition = (entityId: bigint) => { - const position = getComponentValue(Position, getEntityIdFromKeys([entityId])); + const getOwnedEntityOnPosition = (entityId: ID) => { + const position = getComponentValue(Position, getEntityIdFromKeys([BigInt(entityId)])); const depositEntityIds = position ? getOwnedEntitiesOnPosition(BigInt(account.address), { x: Number(position.x), y: Number(position.y) }) : []; diff --git a/client/src/hooks/helpers/useRoads.tsx b/client/src/hooks/helpers/useRoads.tsx deleted file mode 100644 index 50b9b6d36..000000000 --- a/client/src/hooks/helpers/useRoads.tsx +++ /dev/null @@ -1,147 +0,0 @@ -import { RoadInterface } from "@bibliothecadao/eternum"; -import { useComponentValue, useEntityQuery } from "@dojoengine/react"; -import { Entity, HasValue, getComponentValue, runQuery } from "@dojoengine/recs"; -import { useEffect, useMemo, useState } from "react"; -import { getRealm, getRealmIdByPosition, getRealmNameById } from "../../ui/utils/realms"; -import { getEntityIdFromKeys, getPosition } from "../../ui/utils/utils"; -import { useDojo } from "../context/DojoContext"; -import useRealmStore from "../store/useRealmStore"; - -export function useRoads() { - const { - setup: { - components: { Road, Position }, - }, - } = useDojo(); - - const getHasRoad = (entityA: bigint | undefined, entityB: bigint | undefined): boolean | undefined => { - if (entityA && entityB) { - const positionA = getComponentValue(Position, getEntityIdFromKeys([BigInt(entityA)])); - const positionB = getComponentValue(Position, getEntityIdFromKeys([BigInt(entityB)])); - - const road1 = getComponentValue( - Road, - getEntityIdFromKeys([ - BigInt(positionA?.x || 0), - BigInt(positionA?.y || 0), - BigInt(positionB?.x || 0), - BigInt(positionB?.y || 0), - ]), - ); - - const road2 = getComponentValue( - Road, - getEntityIdFromKeys([ - BigInt(positionB?.x || 0), - BigInt(positionB?.y || 0), - BigInt(positionA?.x || 0), - BigInt(positionA?.y || 0), - ]), - ); - - const road1Count = road1?.usage_count || 0; - const road2Count = road2?.usage_count || 0; - - return road1Count > 1 || road2Count > 1; - } else { - false; - } - }; - - return { getHasRoad }; -} - -export function useGetRoads(entityId: bigint) { - const { - setup: { - components: { Road, Position, Realm }, - }, - } = useDojo(); - - const realmId = useRealmStore((state) => state.realmId); - - const [roads, setRoads] = useState([]); - - const position = useComponentValue(Position, getEntityIdFromKeys([BigInt(entityId)])); - - const entityIds1 = useEntityQuery([ - HasValue(Road, { start_coord_x: position?.x || 0, start_coord_y: position?.y || 0 }), - ]); - - const entityIds2 = useEntityQuery([HasValue(Road, { end_coord_x: position?.x || 0, end_coord_y: position?.y || 0 })]); - - const entityIds: Entity[] = useMemo(() => { - return [...entityIds1, ...entityIds2]; - }, [entityIds1, entityIds2]); - - // TODO: put somewhere else for reuse - const getRealmEntityIdFromRealmId = (realmId: bigint): bigint | undefined => { - const entityIds = Array.from(runQuery([HasValue(Realm, { realm_id: realmId })])); - if (entityIds.length > 0) { - let realm = getComponentValue(Realm, entityIds[0]); - return realm!.entity_id; - } - }; - - useEffect(() => { - let roads: RoadInterface[] = entityIds - .map((entityId: Entity) => { - let road = getComponentValue(Road, entityId); - if (road) { - // TODO: refactor to just do one query per realm - let startRealmId = realmId; - - let startRealmName = startRealmId ? getRealmNameById(startRealmId) : ""; - - let { order: startRealmOrder } = startRealmId - ? getRealm(startRealmId) || { order: undefined } - : { order: undefined }; - - let startRealmPosition = getPosition(startRealmId || 0n); - - let destinationRealmId = - startRealmPosition.x === road.start_coord_x && startRealmPosition.y === road.start_coord_y - ? getRealmIdByPosition({ x: road.end_coord_x, y: road.end_coord_y }) - : getRealmIdByPosition({ x: road.start_coord_x, y: road.start_coord_y }); - - let destinationRealmName = destinationRealmId ? getRealmNameById(BigInt(destinationRealmId)) : ""; - - let destinationEntityId = getRealmEntityIdFromRealmId(BigInt(destinationRealmId || 0n)) || 0n; - - let { order: destinationRealmOrder } = destinationRealmId - ? getRealm(BigInt(destinationRealmId)) || { order: undefined } - : { order: undefined }; - - return { - startRealmName, - startRealmOrder, - startEntityId: entityId, - destinationEntityId, - destinationRealmName, - destinationRealmOrder, - usageLeft: road.usage_count, - }; - } - }) - .filter(Boolean) as RoadInterface[]; - - // Group roads by destinationRealmName and keep the one with the highest usageLeft for each destination - const uniqueRoads = Object.values( - roads.reduce( - (acc, road) => { - if (!acc[road.destinationRealmName] || acc[road.destinationRealmName].usageLeft < road.usageLeft) { - acc[road.destinationRealmName] = road; - } - return acc; - }, - {} as { [key: string]: RoadInterface }, - ), - ); - - setRoads(uniqueRoads); - }, [entityIds]); - - return { - roads, - }; -} diff --git a/client/src/hooks/helpers/useStamina.tsx b/client/src/hooks/helpers/useStamina.tsx index 8dd317ef6..6e012a876 100644 --- a/client/src/hooks/helpers/useStamina.tsx +++ b/client/src/hooks/helpers/useStamina.tsx @@ -1,5 +1,4 @@ -import { ClientComponents } from "@/dojo/createClientComponents"; -import { EternumGlobalConfig, ResourcesIds, WORLD_CONFIG_ID } from "@bibliothecadao/eternum"; +import { EternumGlobalConfig, ID, ResourcesIds, WORLD_CONFIG_ID } from "@bibliothecadao/eternum"; import { useEntityQuery } from "@dojoengine/react"; import { Component, Has, HasValue, getComponentValue, runQuery } from "@dojoengine/recs"; import { getEntityIdFromKeys } from "@dojoengine/utils"; @@ -15,17 +14,17 @@ export const useStamina = () => { const currentArmiesTick = useBlockchainStore((state) => state.currentArmiesTick); - const useStaminaByEntityId = ({ travelingEntityId }: { travelingEntityId: bigint }) => { + const useStaminaByEntityId = ({ travelingEntityId }: { travelingEntityId: ID }) => { const staminasEntityIds = useEntityQuery([HasValue(Stamina, { entity_id: travelingEntityId })]); let staminaEntity = getComponentValue(Stamina, staminasEntityIds[0]); const armiesEntityIds = runQuery([Has(Army), HasValue(Army, { entity_id: travelingEntityId })]); const armyEntity = getComponentValue(Army, Array.from(armiesEntityIds)[0]); - if (staminaEntity && armyEntity && currentArmiesTick !== staminaEntity.last_refill_tick) { + if (staminaEntity && armyEntity && BigInt(currentArmiesTick) !== staminaEntity.last_refill_tick) { staminaEntity = { ...staminaEntity, - last_refill_tick: currentArmiesTick, + last_refill_tick: BigInt(currentArmiesTick), amount: getMaxStamina(armyEntity.troops, StaminaConfig), }; } @@ -36,7 +35,7 @@ export const useStamina = () => { travelingEntityId, currentArmiesTick, }: { - travelingEntityId: bigint; + travelingEntityId: ID; currentArmiesTick: number; }) => { const staminasEntityIds = runQuery([HasValue(Stamina, { entity_id: travelingEntityId })]); @@ -45,17 +44,17 @@ export const useStamina = () => { const armiesEntityIds = runQuery([Has(Army), HasValue(Army, { entity_id: travelingEntityId })]); const armyEntity = getComponentValue(Army, Array.from(armiesEntityIds)[0]); - if (staminaEntity && currentArmiesTick !== staminaEntity?.last_refill_tick) { + if (staminaEntity && BigInt(currentArmiesTick) !== staminaEntity?.last_refill_tick) { staminaEntity = { ...staminaEntity!, - last_refill_tick: currentArmiesTick, + last_refill_tick: BigInt(currentArmiesTick), amount: getMaxStamina(armyEntity!.troops, StaminaConfig), }; } return staminaEntity; }; - const getMaxStaminaByEntityId = (travelingEntityId: bigint): number => { + const getMaxStaminaByEntityId = (travelingEntityId: ID): number => { const armiesEntityIds = runQuery([Has(Army), HasValue(Army, { entity_id: travelingEntityId })]); const armyEntity = getComponentValue(Army, Array.from(armiesEntityIds)[0]); if (!armyEntity) return 0; @@ -64,8 +63,8 @@ export const useStamina = () => { return maxStamina; }; - const optimisticStaminaUpdate = (overrideId: string, entityId: bigint, cost: number, currentArmiesTick: number) => { - const entity = getEntityIdFromKeys([entityId]); + const optimisticStaminaUpdate = (overrideId: string, entityId: ID, cost: number, currentArmiesTick: number) => { + const entity = getEntityIdFromKeys([BigInt(entityId)]); const stamina = getStamina({ travelingEntityId: entityId, currentArmiesTick }); @@ -73,7 +72,7 @@ export const useStamina = () => { entity, value: { entity_id: entityId, - last_refill_tick: stamina?.last_refill_tick || 0, + last_refill_tick: stamina?.last_refill_tick || 0n, amount: stamina?.amount ? stamina.amount - cost : 0, }, }); @@ -84,7 +83,7 @@ export const useStamina = () => { return entityArmies.filter((entity: any) => { const stamina = getStamina({ - travelingEntityId: BigInt(entity.entity_id), + travelingEntityId: entity.entity_id, currentArmiesTick, }); return (stamina?.amount || 0) >= EternumGlobalConfig.stamina.travelCost; diff --git a/client/src/hooks/helpers/useStructures.tsx b/client/src/hooks/helpers/useStructures.tsx index a74ed5e79..c4fb46195 100644 --- a/client/src/hooks/helpers/useStructures.tsx +++ b/client/src/hooks/helpers/useStructures.tsx @@ -2,7 +2,7 @@ import { ClientComponents } from "@/dojo/createClientComponents"; import { unpackResources } from "@/ui/utils/packedData"; import { getRealm, getRealmNameById } from "@/ui/utils/realms"; import { calculateDistance } from "@/ui/utils/utils"; -import { EternumGlobalConfig, Position, StructureType } from "@bibliothecadao/eternum"; +import { ContractAddress, EternumGlobalConfig, ID, Position, StructureType } from "@bibliothecadao/eternum"; import { useEntityQuery } from "@dojoengine/react"; import { ComponentValue, Has, HasValue, getComponentValue, runQuery } from "@dojoengine/recs"; import { getEntityIdFromKeys } from "@dojoengine/utils"; @@ -11,13 +11,6 @@ import { shortString } from "starknet"; import { useDojo } from "../context/DojoContext"; import { ArmyInfo, getArmyByEntityId } from "./useArmies"; -export type Realm = ComponentValue & { - resources: number[]; - self: boolean; - name: string; - protector: ArmyInfo | undefined; -}; - export type Structure = ComponentValue & { isMine: boolean; isMercenary: boolean; @@ -27,104 +20,6 @@ export type Structure = ComponentValue entityOwner: ComponentValue; }; -export type FullStructure = ComponentValue & { - entityOwner: ComponentValue; - owner: ComponentValue; - protector: ArmyInfo | undefined; - isMine: boolean; -}; - -export const useStructuresPosition = ({ position }: { position: Position }) => { - const { - setup: { - components: { Position, Realm, EntityOwner, Owner, Structure, Protector, EntityName }, - }, - account: { account }, - } = useDojo(); - - const { getAliveArmy } = getArmyByEntityId(); - - const useFormattedRealmAtPosition = () => { - const realmsAtPosition = useEntityQuery([ - HasValue(Position, { x: position.x, y: position.y }), - HasValue(Structure, { category: StructureType[StructureType.Realm] }), - ]); - const formattedRealmAtPosition: Realm | undefined = realmsAtPosition.map((realm_entity_id: any) => { - const realm = getComponentValue(Realm, realm_entity_id); - if (!realm) return; - const entityOwner = getComponentValue(EntityOwner, realm_entity_id); - if (!entityOwner) return; - const owner = getComponentValue(Owner, getEntityIdFromKeys([entityOwner?.entity_owner_id || 0n])); - if (!owner) return; - const resources = unpackResources(BigInt(realm?.resource_types_packed || 0n), realm?.resource_types_count || 0); - const name = getRealmNameById(BigInt(realm?.realm_id) || 0n); - - const protectorArmy = getComponentValue(Protector, realm_entity_id); - const protector = protectorArmy ? getAliveArmy(BigInt(protectorArmy.army_id)) : undefined; - - const fullRealm = { - ...realm, - protector: protector as ArmyInfo | undefined, - resources, - self: owner?.address === BigInt(account.address), - name: name, - }; - return fullRealm; - })[0]; - - return formattedRealmAtPosition; - }; - - const useFormattedStructureAtPosition = () => { - // structures at position - const structuresAtPosition = useEntityQuery([HasValue(Position, position), Has(Structure)]); - - const formattedStructureAtPosition: Structure | undefined = structuresAtPosition.map((entityId: any) => { - const structure = getComponentValue(Structure, entityId); - if (!structure) { - return; - } - - const entityOwner = getComponentValue(EntityOwner, entityId); - if (!entityOwner) return; - const owner = getComponentValue(Owner, getEntityIdFromKeys([entityOwner?.entity_owner_id || 0n])); - if (!owner) return; - const protectorArmy = getComponentValue(Protector, entityId); - const protector = protectorArmy ? getAliveArmy(BigInt(protectorArmy.army_id)) : undefined; - - const onChainName = getComponentValue(EntityName, entityId); - - const name = onChainName - ? shortString.decodeShortString(onChainName.name.toString()) - : `${String(structure.category) - .replace(/([A-Z])/g, " $1") - .trim()} ${structure?.entity_id}`; - - return { - ...structure, - entityOwner, - owner, - name, - protector: protector as ArmyInfo | undefined, - isMine: BigInt(owner?.address || 0) === BigInt(account.address), - isMercenary: owner.address === 0n, - }; - })[0]; - - return formattedStructureAtPosition; - }; - - const hasStructuresAtPosition = () => { - return useEntityQuery([HasValue(Position, position), Has(Structure)]).length > 0; - }; - - return { - useFormattedRealmAtPosition, - useFormattedStructureAtPosition, - hasStructuresAtPosition, - }; -}; - export const getStructureAtPosition = ({ x, y }: Position): Structure | undefined => { const { account: { account }, @@ -144,11 +39,11 @@ export const getStructureAtPosition = ({ x, y }: Position): Structure | undefine const entityOwner = getComponentValue(EntityOwner, structureEntityId); if (!entityOwner) return; - const ownerOnChain = getComponentValue(Owner, getEntityIdFromKeys([entityOwner?.entity_owner_id || 0n])); - const owner = ownerOnChain ? ownerOnChain : { entity_id: structure.entity_id, address: BigInt(0) }; + const ownerOnChain = getComponentValue(Owner, getEntityIdFromKeys([BigInt(entityOwner?.entity_owner_id || 0)])); + const owner = ownerOnChain ? ownerOnChain : { entity_id: structure.entity_id, address: ContractAddress(0n) }; const protectorArmy = getComponentValue(Protector, structureEntityId); - const protector = protectorArmy ? getAliveArmy(BigInt(protectorArmy.army_id)) : undefined; + const protector = protectorArmy ? getAliveArmy(protectorArmy.army_id) : undefined; const onChainName = getComponentValue(EntityName, structureEntityId); @@ -167,7 +62,7 @@ export const getStructureAtPosition = ({ x, y }: Position): Structure | undefine owner, name, protector, - isMine: BigInt(owner?.address || 0) === BigInt(account.address), + isMine: ContractAddress(owner?.address || 0n) === ContractAddress(account.address), isMercenary: owner.address === 0n, }; }, [x, y]); @@ -194,11 +89,11 @@ export const getStructureByPosition = () => { const entityOwner = getComponentValue(EntityOwner, structureEntityId); if (!entityOwner) return; - const ownerOnChain = getComponentValue(Owner, getEntityIdFromKeys([entityOwner?.entity_owner_id || 0n])); - const owner = ownerOnChain ? ownerOnChain : { entity_id: structure.entity_id, address: BigInt(0) }; + const ownerOnChain = getComponentValue(Owner, getEntityIdFromKeys([BigInt(entityOwner?.entity_owner_id || 0)])); + const owner = ownerOnChain ? ownerOnChain : { entity_id: structure.entity_id, address: ContractAddress(0n) }; const protectorArmy = getComponentValue(Protector, structureEntityId); - const protector = protectorArmy ? getAliveArmy(BigInt(protectorArmy.army_id)) : undefined; + const protector = protectorArmy ? getAliveArmy(protectorArmy.army_id) : undefined; const onChainName = getComponentValue(EntityName, structureEntityId); @@ -217,7 +112,7 @@ export const getStructureByPosition = () => { owner, name, protector, - isMine: BigInt(owner?.address || 0) === BigInt(account.address), + isMine: ContractAddress(owner?.address || 0n) === ContractAddress(account.address), isMercenary: owner.address === 0n, }; }; @@ -225,7 +120,7 @@ export const getStructureByPosition = () => { return structureAtPosition; }; -export const getStructureByEntityId = (entityId: bigint) => { +export const getStructureByEntityId = (entityId: ID) => { const { account: { account }, setup: { @@ -236,18 +131,18 @@ export const getStructureByEntityId = (entityId: bigint) => { const { getAliveArmy } = getArmyByEntityId(); const structure = useMemo(() => { - const structureEntityId = getEntityIdFromKeys([entityId]); + const structureEntityId = getEntityIdFromKeys([BigInt(entityId)]); const structure = getComponentValue(Structure, structureEntityId); if (!structure) return; const entityOwner = getComponentValue(EntityOwner, structureEntityId); if (!entityOwner) return; - const ownerOnChain = getComponentValue(Owner, getEntityIdFromKeys([entityOwner?.entity_owner_id || 0n])); - const owner = ownerOnChain ? ownerOnChain : { entity_id: structure.entity_id, address: BigInt(0) }; + const ownerOnChain = getComponentValue(Owner, getEntityIdFromKeys([BigInt(entityOwner?.entity_owner_id || 0)])); + const owner = ownerOnChain ? ownerOnChain : { entity_id: structure.entity_id, address: ContractAddress(0n) }; const protectorArmy = getComponentValue(Protector, structureEntityId); - const protector = protectorArmy ? getAliveArmy(BigInt(protectorArmy.army_id)) : undefined; + const protector = protectorArmy ? getAliveArmy(protectorArmy.army_id) : undefined; const onChainName = getComponentValue(EntityName, structureEntityId); @@ -266,7 +161,7 @@ export const getStructureByEntityId = (entityId: bigint) => { owner, name, protector, - isMine: BigInt(owner?.address || 0) === BigInt(account.address), + isMine: ContractAddress(owner?.address || 0n) === ContractAddress(account.address), isMercenary: owner.address === 0n, }; }, [entityId]); diff --git a/client/src/hooks/helpers/useTrade.tsx b/client/src/hooks/helpers/useTrade.tsx index 51fafc93d..8343a5783 100644 --- a/client/src/hooks/helpers/useTrade.tsx +++ b/client/src/hooks/helpers/useTrade.tsx @@ -1,15 +1,12 @@ import { getRealmNameById } from "@/ui/utils/realms"; -import { MarketInterface, Resource, ResourcesIds } from "@bibliothecadao/eternum"; +import { ID, MarketInterface, Resource, ResourcesIds } from "@bibliothecadao/eternum"; import { useEntityQuery } from "@dojoengine/react"; import { Entity, HasValue, getComponentValue } from "@dojoengine/recs"; -import { useEffect, useMemo, useState } from "react"; +import { useMemo, useState } from "react"; import { shortString } from "starknet"; -import { calculateRatio } from "../../ui/components/cityview/realm/trade/Market/MarketOffer"; -import { SortInterface } from "../../ui/elements/SortButton"; import { getEntityIdFromKeys } from "../../ui/utils/utils"; import { useDojo } from "../context/DojoContext"; import useBlockchainStore from "../store/useBlockchainStore"; -import useMarketStore from "../store/useMarketStore"; import useRealmStore from "../store/useRealmStore"; import { useEntities } from "./useEntities"; @@ -23,26 +20,26 @@ type TradeResources = { makerGets: Resource[]; }; -export function useTrade() { +function useTrade() { const { setup: { components: { Resource, Trade, Realm, DetachedResource, EntityName }, }, } = useDojo(); - const getDetachedResources = (entityId: bigint): Resource[] => { + const getDetachedResources = (entityId: ID): Resource[] => { let resources = []; let index = 0n; - let detachedResource = getComponentValue(DetachedResource, getEntityIdFromKeys([entityId, index])); + let detachedResource = getComponentValue(DetachedResource, getEntityIdFromKeys([BigInt(entityId), index])); while (detachedResource) { resources.push({ resourceId: detachedResource.resource_type, amount: Number(detachedResource.resource_amount) }); index++; - detachedResource = getComponentValue(DetachedResource, getEntityIdFromKeys([entityId, index])); + detachedResource = getComponentValue(DetachedResource, getEntityIdFromKeys([BigInt(entityId), index])); } return resources; }; - const getTradeResources = (tradeId: bigint): TradeResources => { + const getTradeResources = (tradeId: ID): TradeResources => { let trade = getComponentValue(Trade, getEntityIdFromKeys([BigInt(tradeId)])); if (!trade) return { takerGets: [], makerGets: [] }; @@ -54,7 +51,7 @@ export function useTrade() { return { takerGets, makerGets }; }; - const getTradeResourcesFromEntityViewpoint = (entityId: bigint, tradeId: bigint): TradeResourcesFromViewpoint => { + const getTradeResourcesFromEntityViewpoint = (entityId: ID, tradeId: ID): TradeResourcesFromViewpoint => { let trade = getComponentValue(Trade, getEntityIdFromKeys([BigInt(tradeId)])); if (!trade) return { resourcesGet: [], resourcesGive: [] }; @@ -78,15 +75,15 @@ export function useTrade() { let trade = getComponentValue(Trade, id); if (trade) { const { takerGets, makerGets } = getTradeResources(trade.trade_id); - const makerRealm = getComponentValue(Realm, getEntityIdFromKeys([trade.maker_id])); + const makerRealm = getComponentValue(Realm, getEntityIdFromKeys([BigInt(trade.maker_id)])); - const makerName = getComponentValue(EntityName, getEntityIdFromKeys([trade.maker_id]))?.name; + const makerName = getComponentValue(EntityName, getEntityIdFromKeys([BigInt(trade.maker_id)]))?.name; - const realm = getComponentValue(Realm, getEntityIdFromKeys([trade.maker_id])); + const realm = getComponentValue(Realm, getEntityIdFromKeys([BigInt(trade.maker_id)])); if (trade.expires_at > nextBlockTimestamp) { return { makerName: shortString.decodeShortString(makerName?.toString() || ""), - originName: getRealmNameById(BigInt(realm?.realm_id || 0n)), + originName: getRealmNameById(realm?.realm_id || 0), tradeId: trade.trade_id, makerId: trade.maker_id, takerId: trade.taker_id, @@ -111,14 +108,14 @@ export function useTrade() { realmEntityId, resourcesGive, }: { - realmEntityId: bigint; + realmEntityId: ID; resourcesGive: Resource[]; }): boolean => { let canAccept = true; Object.values(resourcesGive).forEach((resource) => { const realmResource = getComponentValue( Resource, - getEntityIdFromKeys([realmEntityId, BigInt(resource.resourceId)]), + getEntityIdFromKeys([BigInt(realmEntityId), BigInt(resource.resourceId)]), ); if (realmResource === undefined || realmResource.balance < resource.amount) { canAccept = false; @@ -174,7 +171,7 @@ export function useSetMarket() { const { computeTrades } = useTrade(); - const allMarket = useEntityQuery([HasValue(Status, { value: 0n }), HasValue(Trade, { taker_id: 0n })]); + const allMarket = useEntityQuery([HasValue(Status, { value: 0n }), HasValue(Trade, { taker_id: 0 })]); const allTrades = useMemo(() => { return computeTrades(allMarket, nextBlockTimestamp!); @@ -207,72 +204,14 @@ export function useSetMarket() { }; } -export function useSetDirectOffers() { - const { - setup: { - components: { Status, Trade }, - }, - } = useDojo(); - - const { computeTrades } = useTrade(); - const nextBlockTimestamp = useBlockchainStore((state) => state.nextBlockTimestamp); - - const realmEntityId = useRealmStore((state) => state.realmEntityId); - const setDirectOffers = useMarketStore((state) => state.setDirectOffers); - - const entityIds = useEntityQuery([HasValue(Status, { value: 0n }), HasValue(Trade, { taker_id: realmEntityId })]); - - useEffect(() => { - if (!nextBlockTimestamp) return; - const trades = computeTrades(entityIds, nextBlockTimestamp); - setDirectOffers(trades); - }, [entityIds, nextBlockTimestamp]); -} - -/** - * sort trades based on active filters - */ -export function sortTrades(trades: MarketInterface[], _activeSort: SortInterface): MarketInterface[] { - // todo: find a way to sort even though not in marketinterface anymore - - // if (activeSort.sort !== "none") { - // if (activeSort.sortKey === "ratio") { - // return trades.sort((a, b) => { - // if (activeSort.sort === "asc") { - // return a.ratio - b.ratio; - // } else { - // return b.ratio - a.ratio; - // } - // }); - // } else if (activeSort.sortKey === "time") { - // return trades.sort((a, b) => { - // if (activeSort.sort === "asc") { - // return a.expiresAt - b.expiresAt; - // } else { - // return b.expiresAt - a.expiresAt; - // } - // }); - // } else if (activeSort.sortKey === "distance") { - // return trades.sort((a, b) => { - // if (activeSort.sort === "asc") { - // return a.distance - b.distance; - // } else { - // return b.distance - a.distance; - // } - // }); - // } else if (activeSort.sortKey === "realm") { - // return trades.sort((a, b) => { - // if (activeSort.sort === "asc") { - // return Number(a.makerId - b.makerId); - // } else { - // return Number(b.makerId - a.makerId); - // } - // }); - // } else { - // return trades; - // } - // } else { - // return trades.sort((a, b) => Number(b!.tradeId - a!.tradeId)); - // } - return trades; -} +const calculateRatio = (resourcesGive: Resource[], resourcesGet: Resource[]) => { + let quantityGive = 0; + for (let i = 0; i < resourcesGive.length; i++) { + quantityGive += resourcesGive[i].amount; + } + let quantityGet = 0; + for (let i = 0; i < resourcesGet.length; i++) { + quantityGet += resourcesGet[i].amount; + } + return quantityGet / quantityGive; +}; diff --git a/client/src/hooks/helpers/useTravel.tsx b/client/src/hooks/helpers/useTravel.tsx index 0efcc8a03..115a9967b 100644 --- a/client/src/hooks/helpers/useTravel.tsx +++ b/client/src/hooks/helpers/useTravel.tsx @@ -1,12 +1,12 @@ import { calculateDistance } from "@/ui/utils/utils"; -import { EternumGlobalConfig, Position } from "@bibliothecadao/eternum"; +import { EternumGlobalConfig, ID, Position } from "@bibliothecadao/eternum"; import { getComponentValue } from "@dojoengine/recs"; import { getEntityIdFromKeys } from "@dojoengine/utils"; import { uuid } from "@latticexyz/utils"; import { useDojo } from "../context/DojoContext"; import { useStamina } from "./useStamina"; interface TravelToHexProps { - travelingEntityId: bigint | undefined; + travelingEntityId: ID | undefined; directions: number[]; path: Position[]; currentArmiesTick: number; @@ -22,9 +22,9 @@ export function useTravel() { } = useDojo(); const { optimisticStaminaUpdate } = useStamina(); - const computeTravelTime = (fromId: bigint, toId: bigint, speed: number, pickup?: boolean) => { - const fromPosition = getComponentValue(components.Position, getEntityIdFromKeys([fromId])); - const toPosition = getComponentValue(components.Position, getEntityIdFromKeys([toId])); + const computeTravelTime = (fromId: ID, toId: ID, speed: number, pickup?: boolean) => { + const fromPosition = getComponentValue(components.Position, getEntityIdFromKeys([BigInt(fromId)])); + const toPosition = getComponentValue(components.Position, getEntityIdFromKeys([BigInt(toId)])); if (!fromPosition || !toPosition) return; const distanceFromPosition = calculateDistance( @@ -36,7 +36,7 @@ export function useTravel() { }; const optimisticTravelHex = ( - entityId: bigint, + entityId: ID, col: number, row: number, pathLength: number, @@ -44,7 +44,7 @@ export function useTravel() { ) => { let overrideId = uuid(); - const entity = getEntityIdFromKeys([entityId]); + const entity = getEntityIdFromKeys([BigInt(entityId)]); optimisticStaminaUpdate( overrideId, diff --git a/client/src/hooks/store/_mapStore.tsx b/client/src/hooks/store/_mapStore.tsx index f60608adb..32256fb89 100644 --- a/client/src/hooks/store/_mapStore.tsx +++ b/client/src/hooks/store/_mapStore.tsx @@ -2,7 +2,7 @@ import { HyperstructureEventInterface, parseHyperstructureFinishedEventData, } from "@/dojo/events/hyperstructureEventQueries"; -import { Position, StructureType } from "@bibliothecadao/eternum"; +import { ContractAddress, ID, Position, StructureType } from "@bibliothecadao/eternum"; import { useEntityQuery } from "@dojoengine/react"; import { Has, getComponentValue } from "@dojoengine/recs"; import { useEffect, useMemo, useRef, useState } from "react"; @@ -11,7 +11,7 @@ import { useDojo } from "../context/DojoContext"; import useLeaderBoardStore from "./useLeaderBoardStore"; import useUIStore from "./useUIStore"; -export enum ArmyMode { +enum ArmyMode { Travel, Explore, Attack, @@ -24,10 +24,10 @@ export interface MapStore { setClickedHex: (hex: ClickedHex | undefined) => void; hexData: Hexagon[] | undefined; setHexData: (hexData: Hexagon[]) => void; - selectedEntity: { id: bigint; position: Position } | undefined; - setSelectedEntity: (entity: { id: bigint; position: Position } | undefined) => void; - selectedBattle: { id: bigint; position: Position } | undefined; - setSelectedBattle: (battle: { id: bigint; position: Position } | undefined) => void; + selectedEntity: { id: ID; position: Position } | undefined; + setSelectedEntity: (entity: { id: ID; position: Position } | undefined) => void; + selectedBattle: { id: ID; position: Position } | undefined; + setSelectedBattle: (battle: { id: ID; position: Position } | undefined) => void; armyMode: ArmyMode | null; setArmyMode: (mode: ArmyMode | null) => void; travelPaths: Map; @@ -39,9 +39,9 @@ export interface MapStore { clearSelection: () => void; showAllArmies: boolean; toggleShowAllArmies: () => void; - existingStructures: { col: number; row: number; type: StructureType; entityId: bigint }[]; + existingStructures: { col: number; row: number; type: StructureType; entityId: ID }[]; setExistingStructures: ( - existingStructures: { col: number; row: number; type: StructureType; entityId: bigint }[], + existingStructures: { col: number; row: number; type: StructureType; entityId: ID }[], ) => void; } @@ -59,9 +59,9 @@ export const createMapStoreSlice = (set: any) => ({ set({ hexData }); }, selectedEntity: undefined, - setSelectedEntity: (entity: { id: bigint; position: Position } | undefined) => set({ selectedEntity: entity }), + setSelectedEntity: (entity: { id: ID; position: Position } | undefined) => set({ selectedEntity: entity }), selectedBattle: undefined, - setSelectedBattle: (battle: { id: bigint; position: Position } | undefined) => set({ selectedBattle: battle }), + setSelectedBattle: (battle: { id: ID; position: Position } | undefined) => set({ selectedBattle: battle }), armyMode: null, setArmyMode: (armyMode: ArmyMode | null) => set({ armyMode }), travelPaths: new Map(), @@ -90,7 +90,7 @@ export const createMapStoreSlice = (set: any) => ({ }); }, existingStructures: [], - setExistingStructures: (existingStructures: { col: number; row: number; type: StructureType; entityId: bigint }[]) => + setExistingStructures: (existingStructures: { col: number; row: number; type: StructureType; entityId: ID }[]) => set({ existingStructures }), }); @@ -147,7 +147,7 @@ export const useSetExistingStructures = () => { const type = StructureType[structure!.category as keyof typeof StructureType]; if (account.address === masterAccount.address) return null; if (!position || !structure || !owner) return null; - const isMine = owner?.address === BigInt(account.address); + const isMine = owner?.address === ContractAddress(account.address); return { col: Number(position.x), row: Number(position.y), @@ -157,7 +157,7 @@ export const useSetExistingStructures = () => { isMine, }; }) - .filter(Boolean) as { col: number; row: number; type: StructureType; entityId: bigint }[]; + .filter(Boolean) as { col: number; row: number; type: StructureType; entityId: ID }[]; setExistingStructures(_tmp); }, [builtStructures, account.address]); diff --git a/client/src/hooks/store/types.ts b/client/src/hooks/store/types.ts index f1109999b..a69994832 100644 --- a/client/src/hooks/store/types.ts +++ b/client/src/hooks/store/types.ts @@ -1,6 +1,8 @@ +import { ID } from "@bibliothecadao/eternum"; + export type BattleViewInfo = { - battle: bigint | undefined; + battleEntityId: ID | undefined; engage?: boolean; - ownArmyEntityId: bigint | undefined; - targetArmy: bigint | undefined; + ownArmyEntityId: ID | undefined; + targetArmy: ID | undefined; }; diff --git a/client/src/hooks/store/useBlockchainStore.tsx b/client/src/hooks/store/useBlockchainStore.tsx index e3cdfd2db..03d99ba50 100644 --- a/client/src/hooks/store/useBlockchainStore.tsx +++ b/client/src/hooks/store/useBlockchainStore.tsx @@ -53,8 +53,8 @@ export const useFetchBlockchainData = () => { if (timestamp && timestamp !== currentTimestamp) { // Check if fetched timestamp is different from current state setNextBlockTimestamp(timestamp); - setCurrentDefaultTick(Math.floor(timestamp / tickConfigDefault!.tick_interval_in_seconds)); - setCurrentArmiesTick(Math.floor(timestamp / tickConfigArmies!.tick_interval_in_seconds)); + setCurrentDefaultTick(Math.floor(timestamp / Number(tickConfigDefault!.tick_interval_in_seconds))); + setCurrentArmiesTick(Math.floor(timestamp / Number(tickConfigArmies!.tick_interval_in_seconds))); } }; diff --git a/client/src/hooks/store/useCombatHistoryStore.tsx b/client/src/hooks/store/useCombatHistoryStore.tsx deleted file mode 100644 index 4835b38da..000000000 --- a/client/src/hooks/store/useCombatHistoryStore.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { create } from "zustand"; -import { numberToHex } from "../../ui/utils/utils"; -import { pollForEvents, Event } from "../eventPoller"; -import { parseCombatEvent } from "../../ui/utils/combat"; -import { COMBAT_EVENT } from "@bibliothecadao/eternum"; -import { CombatResultInterface } from "@bibliothecadao/eternum"; - -interface CombatHistoryStore { - loading: boolean; - setLoading: (loading: boolean) => void; - progress: number; - setProgress: (progress: number) => void; - combatHistory: CombatResultInterface[]; - addOrUpdateCombatEntry: (result: CombatResultInterface) => void; - syncData: (realmEntityId: bigint) => void; -} - -const useCombatHistoryStore = create((set, get) => ({ - loading: false, - progress: 0, - combatHistory: [], - - setLoading: (loading) => set({ loading }), - setProgress: (progress) => set({ progress }), - - // Function to add or update a leaderboard entry - addOrUpdateCombatEntry: (result: CombatResultInterface) => { - set((state) => { - return { combatHistory: [...state.combatHistory, result] }; - }); - }, - - syncData: async (realmEntityId) => { - set({ loading: true }); - set({ combatHistory: [] }); - - const syncDataInternal = async (realmEntityId: bigint) => { - const processEvents = (event: Event) => { - let result = parseCombatEvent(event); - get().addOrUpdateCombatEntry(result); - }; - - // Keccak for Combat event - await pollForEvents([COMBAT_EVENT, "*", numberToHex(Number(realmEntityId))], processEvents, 20); - }; - - syncDataInternal(realmEntityId).then(() => { - set({ loading: false }); - }); - }, -})); - -export default useCombatHistoryStore; diff --git a/client/src/hooks/store/useLeaderBoardStore.tsx b/client/src/hooks/store/useLeaderBoardStore.tsx index d86e952fc..eb8edcf8e 100644 --- a/client/src/hooks/store/useLeaderBoardStore.tsx +++ b/client/src/hooks/store/useLeaderBoardStore.tsx @@ -1,12 +1,16 @@ +import { ClientComponents } from "@/dojo/createClientComponents"; import { HyperstructureEventInterface, getHyperstructureEvents } from "@/dojo/events/hyperstructureEventQueries"; import { displayAddress, sortItems } from "@/ui/utils/utils"; import { + ContractAddress, EternumGlobalConfig, HYPERSTRUCTURE_POINTS_PER_CYCLE, HYPERSTRUCTURE_TOTAL_COSTS_SCALED, + ID, ResourcesIds, getOrderName, } from "@bibliothecadao/eternum"; +import { ComponentValue } from "@dojoengine/recs"; import { useCallback, useEffect } from "react"; import { create } from "zustand"; import { useDojo } from "../context/DojoContext"; @@ -48,12 +52,11 @@ export const TOTAL_CONTRIBUTABLE_AMOUNT: number = HYPERSTRUCTURE_TOTAL_COSTS_SCA 0, ); -function getResourceMultiplier(resourceType: BigInt): number { - const resourceTypeNumber: ResourcesIds = Number(resourceType); - return ResourceMultipliers[resourceTypeNumber] ?? 0; +function getResourceMultiplier(resourceType: ResourcesIds): number { + return ResourceMultipliers[resourceType] ?? 0; } -export function computeContributionPoints(totalPoints: number, qty: number, resourceType: BigInt): number { +function computeContributionPoints(totalPoints: number, qty: number, resourceType: ResourcesIds): number { const effectiveContribution = (qty / EternumGlobalConfig.resources.resourcePrecision) * getResourceMultiplier(resourceType); const points = (effectiveContribution / TOTAL_CONTRIBUTABLE_AMOUNT) * totalPoints; @@ -63,7 +66,7 @@ export function computeContributionPoints(totalPoints: number, qty: number, reso export const calculateShares = (contributions: any[]) => { let points = 0; contributions.forEach((contribution) => { - points += computeContributionPoints(1, Number(contribution.amount), BigInt(contribution.resource_type)); + points += computeContributionPoints(1, Number(contribution.amount), contribution.resource_type); }); return points; }; @@ -73,7 +76,7 @@ interface Rankable { rank: number; } export interface PlayerPointsLeaderboardInterface { - address: string; + address: ContractAddress; addressName: string; order: string; totalPoints: number; @@ -82,7 +85,7 @@ export interface PlayerPointsLeaderboardInterface { } export interface GuildPointsLeaderboardInterface { - guildEntityId: bigint; + guildEntityId: ID; name: string; totalPoints: number; isYours: boolean; @@ -131,7 +134,7 @@ export const useComputePointsLeaderboards = () => { const updatePlayerPointsLeaderboard = useCallback( ( - hyperstructureEntityId: bigint, + hyperstructureEntityId: ID, finishedTimestamp: number, currentTimestamp: number, ): PlayerPointsLeaderboardInterface[] => { @@ -167,7 +170,7 @@ export const useComputePointsLeaderboards = () => { guildEntityId: userGuildEntityId!, name: guildName!, totalPoints: player.totalPoints, - isYours: player.address === account.address, + isYours: player.address === ContractAddress(account.address), rank: 0, }); } @@ -202,12 +205,12 @@ export const useComputePointsLeaderboards = () => { export default useLeaderBoardStore; -export const computeHyperstructureLeaderboard = ( - contributions: any[], +const computeHyperstructureLeaderboard = ( + contributions: (ComponentValue | undefined)[], totalHyperstructurePoints: number, account: any, - getAddressName: any, - getAddressOrder: any, + getAddressName: (address: ContractAddress) => string | undefined, + getAddressOrder: (address: ContractAddress) => number | undefined, ): PlayerPointsLeaderboardInterface[] => { let tempPlayerPointsLeaderboard: PlayerPointsLeaderboardInterface[] = []; @@ -217,25 +220,25 @@ export const computeHyperstructureLeaderboard = ( } contributions.forEach((contribution) => { - const playerAddress: string = "0x" + contribution!.player_address.toString(16); - const index = tempPlayerPointsLeaderboard.findIndex((player) => player.address === playerAddress); + const index = tempPlayerPointsLeaderboard.findIndex((player) => player.address === contribution!.player_address); if (index >= 0) { tempPlayerPointsLeaderboard[index].totalPoints += computeContributionPoints( totalHyperstructurePoints, Number(contribution!.amount), - BigInt(contribution!.resource_type), + contribution!.resource_type, ); } else { tempPlayerPointsLeaderboard.push({ - address: playerAddress, - addressName: getAddressName(playerAddress) || displayAddress(playerAddress), - order: getOrderName(getAddressOrder(playerAddress) || 1), + address: contribution!.player_address, + addressName: + getAddressName(contribution!.player_address) || displayAddress(contribution!.player_address.toString(16)), + order: getOrderName(getAddressOrder(contribution!.player_address) || 1), totalPoints: computeContributionPoints( totalHyperstructurePoints, Number(contribution!.amount), - BigInt(contribution!.resource_type), + contribution!.resource_type, ), - isYours: playerAddress === account.address, + isYours: contribution!.player_address === account.address, rank: 0, }); } diff --git a/client/src/hooks/store/useMarketStore.tsx b/client/src/hooks/store/useMarketStore.tsx index eeebe52a2..2ecacfe4c 100644 --- a/client/src/hooks/store/useMarketStore.tsx +++ b/client/src/hooks/store/useMarketStore.tsx @@ -1,4 +1,4 @@ -import { MarketInterface, ResourcesIds } from "@bibliothecadao/eternum"; +import { ID, MarketInterface, ResourcesIds } from "@bibliothecadao/eternum"; import { create } from "zustand"; interface MarketStore { @@ -10,7 +10,7 @@ interface MarketStore { refresh: boolean; setRefresh: (refresh: boolean) => void; refreshMarket: () => void; - deleteTrade: (tradeId: bigint) => void; + deleteTrade: (tradeId: ID) => void; setMarkets: (lordsMarket: MarketInterface[], nonLordsMarket: MarketInterface[]) => void; setDirectOffers: (directOffers: MarketInterface[]) => void; selectedResource: number; @@ -32,7 +32,7 @@ const useMarketStore = create((set, get) => { set({ lordsMarket, generalMarket }), setDirectOffers: (directOffers: MarketInterface[]) => set({ directOffers }), setLoading: (loading) => set({ loading }), - deleteTrade: (tradeId: bigint) => { + deleteTrade: (tradeId: ID) => { const lordsMarket = get().lordsMarket.filter((trade) => trade.tradeId !== tradeId); const generalMarket = get().generalMarket.filter((trade) => trade.tradeId !== tradeId); const directOffers = get().directOffers.filter((trade) => trade.tradeId !== tradeId); @@ -46,13 +46,4 @@ const useMarketStore = create((set, get) => { }; }); -export const isLordsMarket = (order: MarketInterface) => { - return ( - order.takerGets.length !== 1 || - order.makerGets.length !== 1 || - (order.takerGets[0]?.resourceId !== ResourcesIds["Lords"] && - order.makerGets[0]?.resourceId !== ResourcesIds["Lords"]) - ); -}; - export default useMarketStore; diff --git a/client/src/hooks/store/useNotificationsStore.tsx b/client/src/hooks/store/useNotificationsStore.tsx deleted file mode 100644 index 82a607f07..000000000 --- a/client/src/hooks/store/useNotificationsStore.tsx +++ /dev/null @@ -1,196 +0,0 @@ -import { create } from "zustand"; -import { BankInterface, CombatInfo, CombatResultInterface, Position, Resource } from "@bibliothecadao/eternum"; - -export enum EventType { - DirectOffer, - AcceptOffer, - CancelOffer, - Harvest, - EmptyChest, - StolenResource, - Attacked, - ArrivedAtBank, - ArrivedAtHyperstructure, - EnemyRaidersHaveArrived, - YourRaidersHaveArrived, - EnemyRaidersArriving, -} - -export enum CarrierType { - Caravan, - Raiders, -} - -export type DirectOfferData = { - takerId: bigint; - makerId: bigint; - tradeId: bigint; -}; - -export type HarvestData = { - harvestAmount: number; -}; - -export type EmptyChestData = { - destinationRealmId: bigint; - carrierType: CarrierType; - entityId: bigint; - realmEntityId: bigint; - indices: number[]; - resources: Resource[]; -}; - -export type ArrivedAtBankData = { - bank: BankInterface; - realmEntityId: bigint; - caravanId: bigint; - indices: number[]; - resources: Resource[]; - lordsAmounts: number[]; - homePosition: Position; -}; - -export type ArrivedAtHyperstructureData = { - hyperstructureId: bigint; - realmEntityId: bigint; - caravanId: bigint; - indices: number[]; - resources: Resource[]; - homePosition: Position; -}; - -export type RaidersData = { - raiders: CombatInfo; -}; - -// todo: use generic data type -export type NotificationType = { - eventType: EventType; - keys: string[] | string | undefined; - data?: - | HarvestData - | EmptyChestData - | CombatResultInterface - | ArrivedAtBankData - | ArrivedAtHyperstructureData - | RaidersData - | DirectOfferData; -}; - -export type exploreNotification = { - entityId: bigint; - biome: string; -}; -interface NotificationsStore { - notifications: NotificationType[]; - setNotifications: (notifications: NotificationType[]) => void; - addUniqueNotifications: (notifications: NotificationType[]) => void; - deleteNotification: (keys: string | string[] | undefined, eventType: EventType) => void; - deleteAllNotifications: () => void; - exploreNotification: exploreNotification | null; - setExploreNotification: (notification: exploreNotification | null) => void; -} - -export const useNotificationsStore = create((set) => ({ - notifications: [], - setNotifications: (notifications) => set({ notifications }), - addUniqueNotifications: (notifications) => { - set((state) => { - let newNotifications = getUniqueNotifications(notifications, state.notifications); - return { notifications: newNotifications }; - }); - }, - deleteNotification: (keys, eventType) => { - set((state) => { - const newNotifications = state.notifications.filter( - (n) => generateUniqueId(n.keys, n.eventType) !== generateUniqueId(keys, eventType), - ); - return { notifications: newNotifications }; - }); - }, - deleteAllNotifications: () => { - set({ notifications: [] }); - }, - exploreNotification: null, - setExploreNotification: (notification: exploreNotification | null) => set({ exploreNotification: notification }), -})); - -/** - * Add unique notifications to the list of notifications - * @param notifications list of notifications - * @param setNotifications setter for notifications - */ -const getUniqueNotifications = ( - notifications: NotificationType[], - prevNotifications: NotificationType[], -): NotificationType[] => { - // Extract keys from previous notifications - const prevIds = new Set(prevNotifications.map((n) => generateUniqueId(n.keys, n.eventType))); - - // Filter out notifications that are already in the prev list - const newNotifications = notifications.filter( - (notification) => !prevIds.has(generateUniqueId(notification.keys, notification.eventType)), - ); - - // If there are no new notifications, return the previous state to avoid re-render - if (newNotifications.length === 0) { - return prevNotifications; - } - - // Otherwise, return the combined list - return [...newNotifications, ...prevNotifications]; -}; - -/** - * Generate unique id for each notification based on keys and eventType - * @param notification - * @returns - */ -export const generateUniqueId = (keys: string | string[] | undefined, eventType: EventType): string => { - return `${eventType}_${extractAndCleanKey(keys).join("_")}`; -}; - -// note: temp change because waiting for torii fix -// export function extractAndCleanKey(keys: (string | null)[]): bigint[] { -// return keys.filter((value) => value !== null && value !== "").map((key) => BigInt(key as string)); -// } -export function extractAndCleanKey(keys: string | null | undefined | string[]): bigint[] { - if (Array.isArray(keys) && keys.length > 0) { - return keys.map((key) => BigInt(key as string)); - } else { - let stringKeys = keys as string | null | undefined; - return ( - stringKeys - ?.split("/") - .slice(0, -1) - .map((key) => BigInt(key as string)) || [] - ); - } -} - -// Function to add last login timestamp to local storage and use it to filter notifications -export const setLastLoginTimestamp = (nextBlockTimestamp: number): void => { - // Store the current timestamp and the next block timestamp as a string - const currentTimestamp = Math.round(Date.now() / 1000); - localStorage.setItem("notificationTimestamp", `${currentTimestamp}-${nextBlockTimestamp}`); -}; - -// Function to retrieve the last login timestamp from local storage -export const getLastLoginTimestamp = (): { lastLoginTimestamp: number; lastLoginBlockTimestamp: number } => { - const storedValue = localStorage.getItem("notificationTimestamp"); - - // If there is no stored value or if it's invalid, return 0 for both timestamps - if (!storedValue) { - return { lastLoginTimestamp: 0, lastLoginBlockTimestamp: 0 }; - } - - const [lastLoginTimestamp, lastLoginBlockTimestamp] = storedValue.split("-").map(Number); - - // Check if both numbers are valid; if not, return 0 for both - if (isNaN(lastLoginTimestamp) || isNaN(lastLoginBlockTimestamp)) { - return { lastLoginTimestamp: 0, lastLoginBlockTimestamp: 0 }; - } - - // Return the parsed numbers - return { lastLoginTimestamp, lastLoginBlockTimestamp }; -}; diff --git a/client/src/hooks/store/useQuestStore.tsx b/client/src/hooks/store/useQuestStore.tsx index fa3ab5eef..51fc2a823 100644 --- a/client/src/hooks/store/useQuestStore.tsx +++ b/client/src/hooks/store/useQuestStore.tsx @@ -1,7 +1,7 @@ import { create } from "zustand"; import { Quest } from "../helpers/useQuests"; -export interface QuestStore { +interface QuestStore { selectedQuest: Quest | null; setSelectedQuest: (selectedQuest: Quest | null) => void; } diff --git a/client/src/hooks/store/useRealmStore.tsx b/client/src/hooks/store/useRealmStore.tsx index 36dcccdf4..c4d6a5c39 100644 --- a/client/src/hooks/store/useRealmStore.tsx +++ b/client/src/hooks/store/useRealmStore.tsx @@ -1,18 +1,19 @@ +import { ID } from "@bibliothecadao/eternum"; import { create } from "zustand"; interface Realm { - realmId: bigint | undefined; - setRealmId: (realmId: bigint) => void; - realmEntityId: bigint; - setRealmEntityId: (realmEntityId: bigint) => void; - realmEntityIds: { realmEntityId: bigint; realmId: bigint }[]; - setRealmEntityIds: (realmEntityIds: { realmEntityId: bigint; realmId: bigint }[]) => void; + realmId: ID | undefined; + setRealmId: (realmId: ID) => void; + realmEntityId: ID; + setRealmEntityId: (realmEntityId: ID) => void; + realmEntityIds: { realmEntityId: ID; realmId: ID }[]; + setRealmEntityIds: (realmEntityIds: { realmEntityId: ID; realmId: ID }[]) => void; } -export const STARTING_ENTITY_ID = 9999n; +const STARTING_ENTITY_ID = 9999; const useRealmStore = create((set) => { - const realmEntityIds: { realmEntityId: bigint; realmId: bigint }[] = []; + const realmEntityIds: { realmEntityId: ID; realmId: ID }[] = []; // TODO: put this as undefined first const realmEntityId = STARTING_ENTITY_ID; @@ -20,13 +21,13 @@ const useRealmStore = create((set) => { return { realmEntityId, - setRealmEntityId: (realmEntityId: bigint) => set({ realmEntityId }), + setRealmEntityId: (realmEntityId: ID) => set({ realmEntityId }), realmEntityIds, - setRealmEntityIds: (realmEntityIds: { realmEntityId: bigint; realmId: bigint }[]) => { + setRealmEntityIds: (realmEntityIds: { realmEntityId: ID; realmId: ID }[]) => { set({ realmEntityIds }); }, realmId, - setRealmId: (realmId: bigint) => set({ realmId }), + setRealmId: (realmId: ID) => set({ realmId }), }; }); diff --git a/client/src/hooks/store/useSystemQueueStore.tsx b/client/src/hooks/store/useSystemQueueStore.tsx deleted file mode 100644 index d3c8e8106..000000000 --- a/client/src/hooks/store/useSystemQueueStore.tsx +++ /dev/null @@ -1,16 +0,0 @@ -// hook to store the list of system calls -import { create } from "zustand"; - -interface SystemQueue { - systemQueue: (() => void)[]; - addToSystemQueue: (system: () => void) => void; - setSystemQueue: (systemQueue: (() => void)[]) => void; -} - -const useSystemQueueStore = create((set) => ({ - systemQueue: [], - addToSystemQueue: (system: () => void) => set((state) => ({ systemQueue: [...state.systemQueue, system] })), - setSystemQueue: (systemQueue: (() => void)[]) => set({ systemQueue }), -})); - -export default useSystemQueueStore; diff --git a/client/src/hooks/store/useUIStore.tsx b/client/src/hooks/store/useUIStore.tsx index b17eb7442..6131e78c2 100644 --- a/client/src/hooks/store/useUIStore.tsx +++ b/client/src/hooks/store/useUIStore.tsx @@ -8,7 +8,6 @@ import { BuildModeStore, createBuildModeStoreSlice } from "./_buildModeStore"; import { createMapStoreSlice, MapStore } from "./_mapStore"; import { createPopupsSlice, PopupsStore } from "./_popups"; import { BattleViewInfo } from "./types"; -export type Background = "map" | "realmView" | "combat" | "bastion"; interface UIStore { theme: string; @@ -110,7 +109,7 @@ const useUIStore = create((se mouseCoords: { x: 0, y: 0 }, setMouseCoords: (coords) => set({ mouseCoords: coords }), moveCameraToRealm: (realmId, speed = undefined) => { - const pos = getRealmUIPosition(BigInt(realmId)); + const pos = getRealmUIPosition(realmId); const x = pos.x; const y = pos.y * -1; const targetPos = new Vector3(x, 0, y); diff --git a/client/src/hooks/useUISound.tsx b/client/src/hooks/useUISound.tsx index 42f36fccc..7cb3564af 100644 --- a/client/src/hooks/useUISound.tsx +++ b/client/src/hooks/useUISound.tsx @@ -209,7 +209,7 @@ export const usePlayResourceSound = () => { }; }; -export const useRunningSound = () => { +const useRunningSound = () => { const { play: playFirst, fade: fadeFirst } = useUiSounds(soundSelector.unitRunning); const { play: playSecond, fade: fadeSecond } = useUiSounds(soundSelector.unitRunningAlternative); const [isFirst, setIsFirst] = useState(true); @@ -234,7 +234,7 @@ export const useRunningSound = () => { }; }; -export const useMarchingSound = () => { +const useMarchingSound = () => { const { repeat: playFirst, stop: stopFirst } = useUiSounds(soundSelector.unitMarching1); const { repeat: playSecond, stop: stopSecond } = useUiSounds(soundSelector.unitMarching2); const [isFirst, setIsFirst] = useState(true); @@ -301,7 +301,7 @@ export const useShovelSound = () => { }; // todo: add battle sounds -export const useBattleSound = () => { +const useBattleSound = () => { const { play: playPillageSucess } = useUiSounds(soundSelector.buildFarm); return { diff --git a/client/src/types/index.ts b/client/src/types/index.ts index d966d273c..bfea7e5b5 100644 --- a/client/src/types/index.ts +++ b/client/src/types/index.ts @@ -1,4 +1,4 @@ -import { Position } from "@bibliothecadao/eternum"; +import { ContractAddress, Position } from "@bibliothecadao/eternum"; export interface Hexagon { idx: number; @@ -6,12 +6,11 @@ export interface Hexagon { row: number; biome: string; explored: boolean | undefined; - // address - exploredBy: bigint | undefined; + exploredBy: ContractAddress | undefined; } -export type Position3D = [number, number, number]; -export type Position2D = [number, number]; +type Position3D = [number, number, number]; +type Position2D = [number, number]; export type HexPosition = { col: number; row: number }; export interface ClickedHex { contractPos: HexPosition; @@ -29,11 +28,6 @@ export interface TravelPath { isExplored: boolean; } -export enum CombatTarget { - Structure, - Army, -} - export interface Health { current: bigint; lifetime: bigint; diff --git a/client/src/ui/components/bank/AddLiquidity.tsx b/client/src/ui/components/bank/AddLiquidity.tsx index d509f48da..416bc79dd 100644 --- a/client/src/ui/components/bank/AddLiquidity.tsx +++ b/client/src/ui/components/bank/AddLiquidity.tsx @@ -4,12 +4,12 @@ import { getResourceBalance } from "@/hooks/helpers/useResources"; import Button from "@/ui/elements/Button"; import { ResourceCost } from "@/ui/elements/ResourceCost"; import { multiplyByPrecision } from "@/ui/utils/utils"; -import { ResourcesIds, resources } from "@bibliothecadao/eternum"; +import { ContractAddress, ID, ResourcesIds, resources } from "@bibliothecadao/eternum"; import { useEffect, useMemo, useState } from "react"; import { ConfirmationPopup } from "./ConfirmationPopup"; import { ResourceBar } from "./ResourceBar"; -const AddLiquidity = ({ bank_entity_id, entityId }: { bank_entity_id: bigint; entityId: bigint }) => { +const AddLiquidity = ({ bank_entity_id, entityId }: { bank_entity_id: ID; entityId: ID }) => { const { account: { account }, setup: { @@ -21,7 +21,7 @@ const AddLiquidity = ({ bank_entity_id, entityId }: { bank_entity_id: bigint; en const { getBalance } = getResourceBalance(); const [isLoading, setIsLoading] = useState(false); - const [resourceId, setResourceId] = useState(1n); + const [resourceId, setResourceId] = useState(ResourcesIds.Wood); const [lordsAmount, setLordsAmount] = useState(0); const [resourceAmount, setResourceAmount] = useState(0); const [openConfirmation, setOpenConfirmation] = useState(false); @@ -32,8 +32,8 @@ const AddLiquidity = ({ bank_entity_id, entityId }: { bank_entity_id: bigint; en components.Market, components.Liquidity, bank_entity_id, - BigInt(account.address), - BigInt(resourceId), + ContractAddress(account.address), + resourceId, ), [components.Market, components.Liquidity, bank_entity_id, resourceId, account.address], ); @@ -108,7 +108,7 @@ const AddLiquidity = ({ bank_entity_id, entityId }: { bank_entity_id: bigint; en amount={Math.floor(lordsAmount)} lordsFee={0} setAmount={setLordsAmount} - resourceId={BigInt(ResourcesIds.Lords)} + resourceId={ResourcesIds.Lords} setResourceId={setResourceId} /> diff --git a/client/src/ui/components/bank/BankEntityList.tsx b/client/src/ui/components/bank/BankEntityList.tsx index 40dc241ed..486b0a0e4 100644 --- a/client/src/ui/components/bank/BankEntityList.tsx +++ b/client/src/ui/components/bank/BankEntityList.tsx @@ -1,4 +1,3 @@ -import useRealmStore from "@/hooks/store/useRealmStore"; import { EntityResourceTable } from "../resources/EntityResourceTable"; export const BankEntityList = ({ entity }: any) => { diff --git a/client/src/ui/components/bank/ConfirmationPopup.tsx b/client/src/ui/components/bank/ConfirmationPopup.tsx index cb0cea5d4..ac2912942 100644 --- a/client/src/ui/components/bank/ConfirmationPopup.tsx +++ b/client/src/ui/components/bank/ConfirmationPopup.tsx @@ -23,7 +23,7 @@ export const ConfirmationPopup: React.FC = ({ }) => { return (
-
+
-
- ); -}; diff --git a/client/src/ui/components/chat/ChatForm.tsx b/client/src/ui/components/chat/ChatForm.tsx deleted file mode 100644 index 214c944cc..000000000 --- a/client/src/ui/components/chat/ChatForm.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { useState } from "react"; -import TextInput from "../../elements/TextInput"; -import Button from "../../elements/Button"; -import Avatar from "../../elements/Avatar"; -import { useChat } from "../../../hooks/context/ChatContext"; -import { addressToNumber } from "../../utils/utils"; -import { useDojo } from "../../../hooks/context/DojoContext"; - -const ChatForm = () => { - const [message, setMessage] = useState(""); - - const { client } = useChat(); - - const handleSendMessage = () => { - client?.message.sendMessage(message); - setMessage(""); - }; - - const handleKeyDown = (event: React.KeyboardEvent) => { - if (event.key === "Enter" && message.trim() !== "") { - handleSendMessage(); - } - }; - - const { - account: { account }, - } = useDojo(); - - return ( -
- - - -
- ); -}; - -export default ChatForm; diff --git a/client/src/ui/components/chat/ChatHistory.tsx b/client/src/ui/components/chat/ChatHistory.tsx deleted file mode 100644 index faf8707f9..000000000 --- a/client/src/ui/components/chat/ChatHistory.tsx +++ /dev/null @@ -1,139 +0,0 @@ -import { useEffect, useRef, useState } from "react"; -import ChatMessage, { ChatMessageProps } from "../../elements/ChatMessage"; -import Button from "../../elements/Button"; -import { useChat } from "../../../hooks/context/ChatContext"; -import { addressToNumber } from "../../utils/utils"; - -interface ChatHistoryProps { - messages: ChatMessageProps[]; -} - -const ChatHistory = (_props: ChatHistoryProps) => { - const [messageList, setMessageList] = useState([]); - - // this should be moved - const [loadingMessages, setLoadingMessages] = useState(false); - - const bottomRef = useRef(null); - - useEffect(() => { - if (bottomRef.current) { - bottomRef.current.scrollIntoView({ behavior: "smooth" }); - } - }, [messageList]); - - const { loginFlow, client, loading, loggedIn } = useChat(); - - // Temp world chat - const group = "group:aaa83cddb7d563d2847d56247060cec696f3d425"; - - // const createRoom = async (groupName: string) => { - // client?.channel.createRoom({ - // groupName, permissions: { - // "group:join": { - // type: "enum", - // value: "public" - // } - // } - // }) - // } - - const setGroup = async (group: string) => { - setLoadingMessages(true); - - await client?.channel.joinGroup(group); - - const { channelList } = client?.channel as any; - - console.log("channelList", channelList); - const channel = channelList?.find((channel: any) => channel.chatid === group); - - await client?.channel.setActiveChannel(channel); - await client?.channel.queryChannels({ - page: 1, - size: 20, - }); - await client?.message.getMessageList({ - page: 1, - size: 20, - }); - - setLoadingMessages(false); - }; - - const transform = (s: string) => s.replace("user:", "0x").slice(0, 2) + "..." + s.slice(-3); - - const handleEvent = (event: { type: any }) => { - const transformToAddress = (s: string) => s.replace("user:", "0x"); - - const format = (message: any) => { - return { - sender: transform(message.senderId), - message: message.content, - avatar: `/images/avatars/${addressToNumber(transformToAddress(message.senderId))}.png`, - timestamp: message.date, - }; - }; - - const list = client?.message.messageList; - - if (event.type === "channel.updated" || event.type == "message.getList") { - console.log("message.getList", list); - setMessageList(list?.map((message: any) => format(message)) || []); - } - }; - - useEffect(() => { - if (!client) return; - client?.channel.queryChannels({ page: 1, size: 20 }); - client?.on("channel.activeChange", handleEvent); - client?.on("channel.created", handleEvent); - client?.on("message.delivered", handleEvent); - client?.on("channel.getList", handleEvent); - client?.on("message.getList", handleEvent); - client?.on("channel.updated", handleEvent); - }, [client]); - - const isLoading = loading || loadingMessages; - - return ( -
-
-   -
- - {isLoading && ( -
-
- -
-
- )} - - {!loggedIn && ( -
- -
- )} - {loggedIn && !messageList.length && ( -
- -
- )} - - {/* */} - - {messageList.map((message, index) => ( - - ))} - - {loggedIn && messageList && } -
- ); -}; - -export default ChatHistory; diff --git a/client/src/ui/components/chat/ChatTabs.tsx b/client/src/ui/components/chat/ChatTabs.tsx deleted file mode 100644 index 36c766f6a..000000000 --- a/client/src/ui/components/chat/ChatTabs.tsx +++ /dev/null @@ -1,157 +0,0 @@ -import { useMemo, useState } from "react"; -import { Tabs } from "../../elements/tab"; -import { ChatMessageProps } from "../../elements/ChatMessage"; -import ChatHistory from "./ChatHistory"; -// import { ChatAccount } from "./ChatAccount"; -// import { ReactComponent as RedDot } from "@/assets/icons/common/red-dot.svg"; - -type ChatTabsProps = {}; - -const dummyMessages: ChatMessageProps[] = [ - { - sender: "loaf.stark", - message: "GM, Adventurers", - avatar: "/images/avatars/1.png", - timestamp: "10:00", - }, - { - sender: "jane.stark", - message: "Hi everyone!", - avatar: "/images/avatars/2.png", - timestamp: "10:05", - }, - { - sender: "bob.stark", - message: "What's the plan?", - avatar: "/images/avatars/3.png", - timestamp: "10:10", - }, - { - sender: "sally.stark", - message: "Let's go to the forest!", - avatar: "/images/avatars/4.png", - timestamp: "10:15", - }, - { - sender: "john.stark", - message: "Sounds like a plan!", - avatar: "/images/avatars/5.png", - timestamp: "10:20", - }, - { - sender: "loaf.stark", - message: "Let's get going!", - avatar: "/images/avatars/1.png", - timestamp: "10:25", - }, - { - sender: "jane.stark", - message: "Wait for me!", - avatar: "/images/avatars/2.png", - timestamp: "10:30", - }, - { - sender: "bob.stark", - message: "I'm ready!", - avatar: "/images/avatars/3.png", - timestamp: "10:35", - }, - { - sender: "sally.stark", - message: "Me too!", - avatar: "/images/avatars/4.png", - timestamp: "10:40", - }, - { - sender: "john.stark", - message: "Let's go!", - avatar: "/images/avatars/5.png", - timestamp: "10:45", - }, - { - sender: "loaf.stark", - message: "Onward!", - avatar: "/images/avatars/1.png", - timestamp: "10:50", - }, - { - sender: "jane.stark", - message: "Be careful out there!", - avatar: "/images/avatars/2.png", - timestamp: "10:55", - }, - { - sender: "bob.stark", - message: "Don't worry, I got this!", - avatar: "/images/avatars/3.png", - timestamp: "11:00", - }, - { - sender: "sally.stark", - message: "Watch out for monsters!", - avatar: "/images/avatars/4.png", - timestamp: "11:05", - }, - { - sender: "john.stark", - message: "We'll be fine!", - avatar: "/images/avatars/5.png", - timestamp: "11:10", - }, -]; - -export const ChatTabs = ({}: ChatTabsProps) => { - const [selectedTab, setSelectedTab] = useState(0); - - const tabs = useMemo( - () => [ - { - label: ( -
-
World Chat
-
- ), - component: , - }, - // { - // label: ( - //
- //
Account
- //
- // ), - // component: , - // }, - // { - // label: ( - //
- //
PM
- // - //
- // ), - // component:
, - // }, - ], - [selectedTab], - ); - - return ( - setSelectedTab(index as number)} - variant="primary" - className="flex-1 -mx-2 overflow-hidden relative z-0" - > - - {tabs.map((tab, index) => ( - {tab.label} - ))} - - - {tabs.map((tab, index) => ( - {tab.component} - ))} -
- - - ); -}; diff --git a/client/src/ui/components/chat/Client.tsx b/client/src/ui/components/chat/Client.tsx deleted file mode 100644 index 3d80e2824..000000000 --- a/client/src/ui/components/chat/Client.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { Client } from "@web3mq/client"; - -// You can save the bestEndpointUrl locally to skip endpoint search next time, which will save time, and -export const bestEndpointUrl = await Client.init({ - connectUrl: "", // - app_key: "OVEEGLRxtqXcEIJN", // temporary authorization key obtained by applying, will be removed in future testnets and mainnet -}); diff --git a/client/src/ui/components/chat/Login.tsx b/client/src/ui/components/chat/Login.tsx deleted file mode 100644 index 4d35291f5..000000000 --- a/client/src/ui/components/chat/Login.tsx +++ /dev/null @@ -1,188 +0,0 @@ -import { Client, WalletType } from "@web3mq/client"; -import { useMemo, useState } from "react"; - -export const useLogin = () => { - const [_didValue, setDidValue] = useState(""); - const password = "123456"; - const didType: WalletType = "argentX"; // or 'starknet'; - - const [userExist, setUserExist] = useState(false); - - const [loggedIn, setLoggedIn] = useState(false); - - const [initUpdate, setInitUpdate] = useState(false); - - const [loading, setLoading] = useState(false); - - const connect = async () => { - const { address: didValue } = await Client.register.getAccount(didType); - setDidValue(didValue); - - const { userid, userExist } = await Client.register.getUserInfo({ - did_value: didValue, - did_type: "starknet", - }); - localStorage.setItem("USER_ID", userid); - - setUserExist(userExist); - - return { userExist, didValue }; - }; - - // 2. create main key pairs - const createKeyPairs = async (didValue: string) => { - const { publicKey: localMainPublicKey, secretKey: localMainPrivateKey } = await Client.register.getMainKeypair({ - password, - did_value: didValue, - did_type: didType, - }); - - localStorage.setItem("MAIN_PRIVATE_KEY", localMainPrivateKey); - localStorage.setItem("MAIN_PUBLIC_KEY", localMainPublicKey); - }; - - const getStorageValue = (key: string) => { - return localStorage.getItem(key) || ""; - }; - - const register = async (didValue: string) => { - const { signContent } = await Client.register.getRegisterSignContent({ - userid: getStorageValue("USER_ID"), - mainPublicKey: getStorageValue("MAIN_PUBLIC_KEY"), - didType, - didValue, - }); - - const { sign: signature, publicKey: did_pubkey = "" } = await Client.register.sign(signContent, didValue, didType); - - const params = { - userid: getStorageValue("USER_ID"), - didValue, - mainPublicKey: getStorageValue("MAIN_PUBLIC_KEY"), - did_pubkey, - didType, - nickname: "", - avatar_url: `https://cdn.stamp.fyi/avatar/${didValue}?s=300`, - signature, - }; - - await Client.register.register(params); - }; - - const login = async (didValue: string) => { - const params = { - password, - mainPublicKey: getStorageValue("MAIN_PUBLIC_KEY"), - mainPrivateKey: getStorageValue("MAIN_PRIVATE_KEY"), - userid: getStorageValue("USER_ID"), - didType, - didValue, - }; - - const { tempPrivateKey, tempPublicKey, pubkeyExpiredTimestamp, mainPrivateKey, mainPublicKey } = - await Client.register.login(params); - - localStorage.setItem("TEMP_PRIVATE_KEY", tempPrivateKey); - localStorage.setItem("TEMP_PUBLIC_KEY", tempPublicKey); - localStorage.setItem("PUBKEY_EXPIRED_TIMESTAMP", String(pubkeyExpiredTimestamp)); - - setLoggedIn(!loggedIn); - - return { - tempPrivateKey, - tempPublicKey, - pubkeyExpiredTimestamp, - mainPrivateKey, - mainPublicKey, - }; - }; - - const expiredKeys = () => { - const timestamp = getStorageValue("PUBKEY_EXPIRED_TIMESTAMP"); - return timestamp ? Number(timestamp) < Date.now() : true; - }; - - const init = async () => { - const fastUrl = await Client.init({ - connectUrl: getStorageValue("FAST_URL"), - app_key: "OVEEGLRxtqXcEIJN", - }); - localStorage.setItem("FAST_URL", fastUrl); - - setInitUpdate(true); - }; - - const hasKeys = useMemo(() => { - const PrivateKey = getStorageValue("TEMP_PRIVATE_KEY"); - const PublicKey = getStorageValue("TEMP_PUBLIC_KEY"); - const userid = getStorageValue("USER_ID"); - if (PrivateKey && PublicKey && userid) { - return { PrivateKey, PublicKey, userid }; - } - return null; - }, [loggedIn]); - - const client = useMemo(() => { - if (hasKeys && initUpdate) { - return Client.getInstance(hasKeys); - } - return null; - }, [hasKeys, loggedIn]); - - const loginFlow = async () => { - setLoading(true); - try { - await init(); - } catch (e) { - console.log("init", e); - } - - const { userExist, didValue } = await connect(); - - if (!hasKeys || expiredKeys()) { - try { - await createKeyPairs(didValue); - } catch (e) { - console.log("key", e); - } - } - - if (userExist) { - try { - await login(didValue); - } catch (e) { - console.log("login", e); - } - } else { - try { - await register(didValue); - } catch (e) { - console.log("register", e); - } finally { - try { - await login(didValue); - } catch (e) { - console.log("login", e); - } - } - } - - setLoading(false); - }; - - return { - login, - init, - connect, - createKeyPairs, - register, - userId: getStorageValue("USER_ID"), - tempPrivateKey: getStorageValue("TEMP_PRIVATE_KEY"), - tempPublicKey: getStorageValue("TEMP_PUBLIC_KEY"), - client, - userExist, - loginFlow, - loading, - loggedIn, - }; -}; diff --git a/client/src/ui/components/cityview/BuildingTooltip.tsx b/client/src/ui/components/cityview/BuildingTooltip.tsx deleted file mode 100644 index 80a21199c..000000000 --- a/client/src/ui/components/cityview/BuildingTooltip.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { BaseThreeTooltip } from "@/ui/elements/BaseThreeTooltip"; -import { findResourceById } from "@bibliothecadao/eternum"; -import ProgressBar from "../../elements/ProgressBar"; -import { ResourceIcon } from "../../elements/ResourceIcon"; - -type BuildingTooltipProps = { - resourceId: number; -}; - -export const BuildingTooltip = ({ resourceId }: BuildingTooltipProps) => { - const resource = findResourceById(resourceId); - - return ( - -
- -
{resource?.trait} Mine
-
-
- +0 - - /h -
-
-
- -
-
Generating
-
- -
{`+500`}
-
-
-
- ); -}; diff --git a/client/src/ui/components/cityview/realm/RealmList.tsx b/client/src/ui/components/cityview/realm/RealmList.tsx deleted file mode 100644 index 4b428bba0..000000000 --- a/client/src/ui/components/cityview/realm/RealmList.tsx +++ /dev/null @@ -1,216 +0,0 @@ -import { useDeferredValue, useEffect, useMemo, useState } from "react"; -import useRealmStore from "../../../../hooks/store/useRealmStore"; -import { SelectableRealmInterface } from "@bibliothecadao/eternum"; -import { OrderIcon } from "../../../elements/OrderIcon"; -import { SortButton, SortInterface } from "../../../elements/SortButton"; -import { SortPanel } from "../../../elements/SortPanel"; -import { ReactComponent as CaretDownFill } from "@/assets/icons/common/caret-down-fill.svg"; -import TextInput from "../../../elements/TextInput"; -import { removeAccents } from "../../../utils/utils"; - -export const RealmList = ({ - selectedRealmEntityId, - setSelectedRealmEntityId, - selectableRealms, - title = "", -}: { - selectedRealmEntityId: bigint | undefined; - setSelectedRealmEntityId: (selectedRealmEntityId: bigint) => void; - selectableRealms: SelectableRealmInterface[]; - title?: string | undefined; -}) => { - const [specifyRealmId, setSpecifyRealmId] = useState(false); - const [nameFilter, setNameFilter] = useState(""); - const [sortedRealms, setSortedRealms] = useState([]); - const deferredNameFilter = useDeferredValue(nameFilter); - - const realmEntityId = useRealmStore((state) => state.realmEntityId); - - const sortingParams = useMemo(() => { - return [ - { label: "Order", sortKey: "order" }, - { label: "Realm ID", sortKey: "id", className: "ml-4" }, - { label: "Realm", sortKey: "name", className: "ml-4 mr-4" }, - { label: "Name", sortKey: "addressName", className: "ml-4 mr-4" }, - { label: "Distance", sortKey: "distance", className: "ml-auto" }, - ]; - }, []); - - const [activeSort, setActiveSort] = useState({ - sortKey: "number", - sort: "none", - }); - - useEffect(() => { - const sorted = sortRealms(selectableRealms, activeSort); - if (nameFilter.length > 0) { - const filtered = sorted.filter((realm) => { - const name = removeAccents(realm.name.toLowerCase()); - return name.includes(deferredNameFilter.toLowerCase()) || realm.realmId.toString().includes(deferredNameFilter); - }); - // sort Realms by index of the name filter - filtered.sort((a, b) => { - const nameA = removeAccents(a.name.toLowerCase()); - const nameB = removeAccents(b.name.toLowerCase()); - const filter = deferredNameFilter.toLowerCase(); - return nameA.indexOf(filter) - nameB.indexOf(filter); - }); - setSortedRealms(filtered); - return; - } - setSortedRealms(sorted); - }, [selectableRealms, activeSort, deferredNameFilter]); - - const selectedRealm = useMemo(() => { - return sortedRealms.find((realm) => realm.entityId === selectedRealmEntityId); - }, [sortedRealms, selectedRealmEntityId]); - - return ( -
- {!specifyRealmId && ( -
setSpecifyRealmId(true)} - className="relative w-full mx-4 h-8 py-[7px] bg-dark-brown cursor-pointer rounded justify-center items-center box-border" - > - {!selectedRealmEntityId ? ( -
+ {title}
- ) : ( -
- {title} for: - {selectedRealm?.name} -
- )} - -
- )} - {specifyRealmId && ( -
-
setSpecifyRealmId(false)} - className="w-full p-2 mb-1 -mt-1 relative cursor-pointer rounded justify-center items-center" - > -
{title}
- -
- {realmEntityId.toString() && ( -
- - - {sortingParams.map(({ label, sortKey, className }) => ( - { - setActiveSort({ - sortKey: _sortKey, - sort: _sort, - }); - }} - /> - ))} - -
- {sortedRealms.map( - ({ order, name, addressName, entityId: takerRealmEntityId, realmId: takerRealmId, distance }, i) => { - return ( -
{ - if (selectedRealmEntityId !== takerRealmEntityId) { - setSelectedRealmEntityId(takerRealmEntityId); - } else { - setSelectedRealmEntityId(0n); - } - }} - > -
-
- -
- -
{Number(takerRealmId)}
- -
{name}
- -
{addressName}
- -
{`${distance.toFixed(0)} km`}
-
-
- ); - }, - )} -
-
- )} -
- )} -
- ); -}; - -/** - * sort realms based on active filters - */ -export function sortRealms(realms: SelectableRealmInterface[], activeSort: SortInterface): SelectableRealmInterface[] { - const sortedRealms = [...realms]; // Making a copy of the realms array - - if (activeSort.sort !== "none") { - if (activeSort.sortKey === "id") { - return sortedRealms.sort((a, b) => { - if (activeSort.sort === "asc") { - return Number(a.realmId - b.realmId); - } else { - return Number(b.realmId - a.realmId); - } - }); - } else if (activeSort.sortKey === "name") { - return sortedRealms.sort((a, b) => { - if (activeSort.sort === "asc") { - return a.name.localeCompare(b.name); - } else { - return b.name.localeCompare(a.name); - } - }); - } else if (activeSort.sortKey === "addressName") { - return sortedRealms.sort((a, b) => { - if (activeSort.sort === "asc") { - return a.addressName.localeCompare(b.addressName); - } else { - return b.addressName.localeCompare(a.addressName); - } - }); - } else if (activeSort.sortKey === "distance") { - return sortedRealms.sort((a, b) => { - if (activeSort.sort === "asc") { - return a.distance - b.distance; - } else { - return b.distance - a.distance; - } - }); - } else if (activeSort.sortKey === "order") { - return sortedRealms.sort((a, b) => { - if (activeSort.sort === "asc") { - return a.order.localeCompare(b.order); - } else { - return b.order.localeCompare(a.order); - } - }); - } else { - return sortedRealms; - } - } else { - return sortedRealms.sort((a, b) => Number(b.realmId - a.realmId)); - } -} diff --git a/client/src/ui/components/cityview/realm/RealmStatusComponent.tsx b/client/src/ui/components/cityview/realm/RealmStatusComponent.tsx deleted file mode 100644 index e41e64249..000000000 --- a/client/src/ui/components/cityview/realm/RealmStatusComponent.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import React from "react"; -import { ReactComponent as SkullIcon } from "@/assets/icons/common/skull.svg"; -import { ReactComponent as ShieldIcon } from "@/assets/icons/common/shield.svg"; -import { ReactComponent as HappyIcon } from "@/assets/icons/common/happy.svg"; - -import clsx from "clsx"; -import { BaseStatus } from "../../../elements/BaseStatus"; - -type RealmStatusComponentProps = {} & React.ComponentPropsWithRef<"div">; - -export const RealmStatusComponent = ({ className }: RealmStatusComponentProps) => { - const realmStatus = { - defence: "vulnerable" as keyof typeof defence, - happiness: "happy" as keyof typeof hapiness, - }; - - const defence = { - vulnerable: { - title: "Vulnerable", - icon: , - }, - weak: { - title: "Weak", - icon: <>, - }, - strong: { - title: "Strong", - icon: <>, - }, - }; - - const hapiness = { - starving: { - title: "People are starving", - icon: , - }, - unhappy: { - title: "People are unhappy", - icon: <>, - }, - happy: { - title: "People are happy", - icon: , - }, - }; - - return ( -
- - {defence[realmStatus.defence].icon} - {defence[realmStatus.defence].title} - - - {hapiness[realmStatus.happiness].icon} - {hapiness[realmStatus.happiness].title} - -
- ); -}; - -export default RealmStatusComponent; diff --git a/client/src/ui/components/cityview/realm/SettleRealmComponent.tsx b/client/src/ui/components/cityview/realm/SettleRealmComponent.tsx index f8681d192..d37e9a839 100644 --- a/client/src/ui/components/cityview/realm/SettleRealmComponent.tsx +++ b/client/src/ui/components/cityview/realm/SettleRealmComponent.tsx @@ -14,7 +14,7 @@ import { getPosition } from "@/ui/utils/utils"; export const MAX_REALMS = 1; -export const SettleRealmComponent = () => { +const SettleRealmComponent = () => { const [isLoading, setIsLoading] = useState(false); const [selectedOrder, setSelectedOrder] = useState(1); diff --git a/client/src/ui/components/cityview/realm/SmallResource.tsx b/client/src/ui/components/cityview/realm/SmallResource.tsx deleted file mode 100644 index 98a1fb65b..000000000 --- a/client/src/ui/components/cityview/realm/SmallResource.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { findResourceById } from "@bibliothecadao/eternum"; -import { ResourceIcon } from "../../../elements/ResourceIcon"; -import { currencyFormat, divideByPrecision } from "../../../utils/utils"; -import useUIStore from "../../../../hooks/store/useUIStore"; -import clsx from "clsx"; - -export const SmallResource = ({ - resourceId, - balance, - vertical, - intlFormat, -}: { - resourceId: number; - balance: number; - entity_id?: bigint; - vertical?: boolean; - intlFormat?: boolean; - hideIfZero?: boolean; -}) => { - const setTooltip = useUIStore((state) => state.setTooltip); - - return balance > 0 ? ( -
- setTooltip({ - position: "bottom", - content: <>{findResourceById(resourceId)?.trait}, - }) - } - onMouseLeave={() => setTooltip(null)} - className={clsx("flex relative group items-center", vertical && "flex-col space-y-1", !vertical && "space-x-1")} - > - -
- {intlFormat - ? Intl.NumberFormat("en-US", { - notation: "compact", - maximumFractionDigits: 1, - }).format(divideByPrecision(balance)) - : currencyFormat(balance, 2)} -
-
- ) : null; -}; diff --git a/client/src/ui/components/cityview/realm/buildings/labor/SelectLaborResourceComponent.tsx b/client/src/ui/components/cityview/realm/buildings/labor/SelectLaborResourceComponent.tsx deleted file mode 100644 index b28ba7d58..000000000 --- a/client/src/ui/components/cityview/realm/buildings/labor/SelectLaborResourceComponent.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { getResourceBalance } from "@/hooks/helpers/useResources"; -import useRealmStore from "@/hooks/store/useRealmStore"; -import { Guilds, resourcesByGuild } from "@bibliothecadao/eternum"; -import { SelectableLaborResource } from "./SelectableLaborResource"; - -interface SelectLaborResourceComponentProps { - guild: number; - selectedLaborResource: number | undefined; - setSelectedLaborResource: (resourceId: number) => void; -} - -export const SelectLaborResourceComponent = ({ - guild, - selectedLaborResource, - setSelectedLaborResource, -}: SelectLaborResourceComponentProps) => { - const realmEntityId = useRealmStore((state) => state.realmEntityId); - const { getBalance } = getResourceBalance(); - - const resources = Guilds[guild - 1] ? resourcesByGuild[Guilds[guild - 1]] : undefined; - - const resourceBalance = resources - ? resources.map((resourceId) => { - return { - resourceId, - amount: getBalance(realmEntityId, resourceId + 28)?.balance || 0, - }; - }) - : undefined; - - return ( -
- {resourceBalance?.map((resource) => { - return ( - { - setSelectedLaborResource(resource.resourceId); - }} - /> - ); - })} -
- ); -}; diff --git a/client/src/ui/components/cityview/realm/buildings/labor/SelectableLaborResource.tsx b/client/src/ui/components/cityview/realm/buildings/labor/SelectableLaborResource.tsx deleted file mode 100644 index 74dcaa209..000000000 --- a/client/src/ui/components/cityview/realm/buildings/labor/SelectableLaborResource.tsx +++ /dev/null @@ -1,170 +0,0 @@ -import React from "react"; -import { Guilds, ResourcesIds, findResourceById } from "@bibliothecadao/eternum"; -import clsx from "clsx"; -import { ResourceIcon } from "../../../../../elements/ResourceIcon"; -import { soundSelector, useUiSounds } from "../../../../../../hooks/useUISound"; -import useUIStore from "../../../../../../hooks/store/useUIStore"; - -type SelectableLaborResourceProps = { - guild: number; - resourceId: number; - amount: number; - selected?: boolean; - disabled?: boolean; -} & React.HTMLAttributes; - -export const SelectableLaborResource = ({ - guild, - resourceId, - amount, - selected, - disabled, - onClick, -}: SelectableLaborResourceProps) => { - const resource = findResourceById(resourceId); - const setTooltip = useUIStore((state) => state.setTooltip); - - const { play: playAddWood } = useUiSounds(soundSelector.addWood); - const { play: playAddStone } = useUiSounds(soundSelector.addStone); - const { play: playAddCoal } = useUiSounds(soundSelector.addCoal); - const { play: playAddCopper } = useUiSounds(soundSelector.addCopper); - const { play: playAddObsidian } = useUiSounds(soundSelector.addObsidian); - const { play: playAddSilver } = useUiSounds(soundSelector.addSilver); - const { play: playAddIronwood } = useUiSounds(soundSelector.addIronwood); - const { play: playAddColdIron } = useUiSounds(soundSelector.addColdIron); - const { play: playAddGold } = useUiSounds(soundSelector.addGold); - const { play: playAddHartwood } = useUiSounds(soundSelector.addHartwood); - const { play: playAddDiamonds } = useUiSounds(soundSelector.addDiamonds); - const { play: playAddSapphire } = useUiSounds(soundSelector.addSapphire); - const { play: playAddRuby } = useUiSounds(soundSelector.addRuby); - const { play: playAddDeepCrystal } = useUiSounds(soundSelector.addDeepCrystal); - const { play: playAddIgnium } = useUiSounds(soundSelector.addIgnium); - const { play: playAddEtherealSilica } = useUiSounds(soundSelector.addEtherealSilica); - - const { play: playAddTrueIce } = useUiSounds(soundSelector.addTrueIce); - const { play: playAddTwilightQuartz } = useUiSounds(soundSelector.addTwilightQuartz); - const { play: playAddAlchemicalSilver } = useUiSounds(soundSelector.addAlchemicalSilver); - const { play: playAddAdamantine } = useUiSounds(soundSelector.addAdamantine); - const { play: playAddMithral } = useUiSounds(soundSelector.addMithral); - const { play: playAddDragonhide } = useUiSounds(soundSelector.addDragonhide); - const { play: playAddWheat } = useUiSounds(soundSelector.addWheat); - const { play: playAddFish } = useUiSounds(soundSelector.addFish); - - const playResourceSound = (resourceId: ResourcesIds) => { - // eslint-disable-next-line sonarjs/no-small-switch - switch (resourceId) { - case ResourcesIds.Wood: - playAddWood(); - break; - case ResourcesIds.Stone: - playAddStone(); - break; - case ResourcesIds.Coal: - playAddCoal(); - break; - case ResourcesIds.Copper: - playAddCopper(); - break; - case ResourcesIds.Obsidian: - playAddObsidian(); - break; - case ResourcesIds.Silver: - playAddSilver(); - break; - case ResourcesIds.Ironwood: - playAddIronwood(); - break; - case ResourcesIds.ColdIron: - playAddColdIron(); - break; - case ResourcesIds.Gold: - playAddGold(); - break; - case ResourcesIds.Hartwood: - playAddHartwood(); - break; - case ResourcesIds.Diamonds: - playAddDiamonds(); - break; - case ResourcesIds.Sapphire: - playAddSapphire(); - break; - case ResourcesIds.Ruby: - playAddRuby(); - break; - case ResourcesIds.DeepCrystal: - playAddDeepCrystal(); - break; - case ResourcesIds.Ignium: - playAddIgnium(); - break; - case ResourcesIds.EtherealSilica: - playAddEtherealSilica(); - break; - case ResourcesIds.TrueIce: - playAddTrueIce(); - break; - case ResourcesIds.TwilightQuartz: - playAddTwilightQuartz(); - break; - case ResourcesIds.AlchemicalSilver: - playAddAlchemicalSilver(); - break; - case ResourcesIds.Adamantine: - playAddAdamantine(); - break; - case ResourcesIds.Mithral: - playAddMithral(); - break; - case ResourcesIds.Dragonhide: - playAddDragonhide(); - break; - case ResourcesIds.Wheat: - playAddWheat(); - break; - case ResourcesIds.Fish: - playAddFish(); - break; - default: - break; - } - }; - - return ( -
- setTooltip({ - position: "bottom", - content: ( - <> -
- {`${resource?.trait} ${Guilds[guild - 1]}`} -
{amount || 0}
-
- - ), - }) - } - onMouseLeave={() => setTooltip(null)} - onClick={(e) => { - if (!disabled && onClick) { - onClick(e); - playResourceSound(resourceId); - } - }} - className={clsx( - "p-2 relative cursor-pointer group border border-transparent transition-colors duration-200 rounded-xl bg-black/60 hover:border-lightest", - selected && "!border-gold", - disabled && "opacity-30 cursor-not-allowed pointer-events-none", - )} - > - -
- ); -}; diff --git a/client/src/ui/components/cityview/realm/labor/laborUtils.tsx b/client/src/ui/components/cityview/realm/labor/laborUtils.tsx deleted file mode 100644 index 0635325aa..000000000 --- a/client/src/ui/components/cityview/realm/labor/laborUtils.tsx +++ /dev/null @@ -1,46 +0,0 @@ -export const formatSecondsInHoursMinutes = (seconds: number) => { - const hours = Math.floor(seconds / 3600); - const minutes = Math.floor((seconds % 3600) / 60); - - return `${hours}h:${minutes}m`; -}; - -export const formatSecondsLeftInDaysHours = (seconds: number) => { - const days = Math.floor(seconds / 86400); - const secondsLeft = seconds % 86400; - const hours = Math.floor(secondsLeft / 3600); - const minutes = Math.floor((secondsLeft % 3600) / 60); - - return `${days} days ${hours}h ${minutes}m`; -}; - -export const calculateProductivity = ( - resources_per_cycle: number, - multiplier: number, - cycle_length: number, - realmLevelBonus: number, - hyperstructureLevelBonus: number, -): number => { - let productivity = (resources_per_cycle * multiplier) / cycle_length; - // in hours - return ((productivity * realmLevelBonus * hyperstructureLevelBonus) / 10000) * 3600; -}; - -// calculates how much you will have when you click on harvest -export const calculateNextHarvest = ( - balance: number, - lastHarvestTimestamp: number, - multiplier: number, - cycleLengthInSeconds: number, - productionPerCycle: number, - nextBlockTimeInSeconds: number, - realmLevelBonus: number, - hyperstructureLevelBonus: number, -): number => { - if (nextBlockTimeInSeconds <= lastHarvestTimestamp) return 0; - - const harvestSeconds = Math.min(balance, nextBlockTimeInSeconds) - lastHarvestTimestamp; - const nextHarvestUnits = Math.floor(harvestSeconds / cycleLengthInSeconds); - - return (nextHarvestUnits * productionPerCycle * multiplier * realmLevelBonus * hyperstructureLevelBonus) / 10000; -}; diff --git a/client/src/ui/components/cityview/realm/trade/AcceptOffer.tsx b/client/src/ui/components/cityview/realm/trade/AcceptOffer.tsx deleted file mode 100644 index 2eaee634a..000000000 --- a/client/src/ui/components/cityview/realm/trade/AcceptOffer.tsx +++ /dev/null @@ -1,114 +0,0 @@ -import { useEffect, useMemo, useState } from "react"; -import Button from "../../../../elements/Button"; -import { useDojo } from "../../../../../hooks/context/DojoContext"; -import useRealmStore from "../../../../../hooks/store/useRealmStore"; -import { useTrade } from "../../../../../hooks/helpers/useTrade"; -import { divideByPrecision } from "../../../../utils/utils"; -import { EternumGlobalConfig, MarketInterface } from "@bibliothecadao/eternum"; -import useMarketStore from "../../../../../hooks/store/useMarketStore"; -import { EventType, useNotificationsStore } from "../../../../../hooks/store/useNotificationsStore"; -import { OSWindow } from "@/ui/components/navigation/OSWindow"; -import { acceptOfferTitle } from "@/ui/components/navigation/Config"; -import { TravelInfo } from "@/ui/components/resources/ResourceWeight"; -import { useTravel } from "@/hooks/helpers/useTravel"; - -type AcceptOfferPopupProps = { - onClose: () => void; - selectedTrade: MarketInterface; - show: boolean; -}; - -export const AcceptOfferPopup = ({ onClose, selectedTrade, show }: AcceptOfferPopupProps) => { - const [canCarry, setCanCarry] = useState(false); - const [isLoading, setIsLoading] = useState(false); - - useEffect(() => { - setIsLoading(false); - }, [selectedTrade]); - - const { - account: { account }, - setup: { - systemCalls: { accept_order }, - }, - } = useDojo(); - - const { computeTravelTime } = useTravel(); - - const realmEntityId = useRealmStore((state) => state.realmEntityId); - - const deleteTrade = useMarketStore((state) => state.deleteTrade); - const deleteNotification = useNotificationsStore((state) => state.deleteNotification); - - const selectedResourceIdsGet = selectedTrade.takerGets.map((resource) => resource.resourceId); - const selectedResourceIdsGive = selectedTrade.makerGets.map((resource) => resource.resourceId); - - const travelTime = useMemo( - () => computeTravelTime(realmEntityId, selectedTrade.makerId, EternumGlobalConfig.speed.donkey, true), - [realmEntityId, selectedTrade], - ); - - const onAccept = async () => { - setIsLoading(true); - // todo: only delete if success - await accept_order({ - signer: account, - taker_id: realmEntityId, - trade_id: selectedTrade.tradeId, - maker_gives_resources: selectedResourceIdsGet.flatMap((id) => [id, selectedResourcesGetAmounts[id]]), - taker_gives_resources: selectedResourceIdsGive.flatMap((id) => [id, selectedResourcesGiveAmounts[id]]), - }); - deleteTrade(selectedTrade.tradeId); - if (selectedTrade.takerId === realmEntityId) { - deleteNotification([selectedTrade.tradeId.toString()], EventType.DirectOffer); - } - onClose(); - }; - - const { getTradeResourcesFromEntityViewpoint } = useTrade(); - - let { resourcesGive, resourcesGet } = getTradeResourcesFromEntityViewpoint(realmEntityId, selectedTrade.tradeId); - - const selectedResourcesGetAmounts = useMemo(() => { - let selectedResourcesGetAmounts: { [resourceId: number]: number } = {}; - resourcesGet.forEach((resource) => { - selectedResourcesGetAmounts[resource.resourceId] = resource.amount; - }); - return selectedResourcesGetAmounts; - }, [selectedTrade]); - - const selectedResourcesGiveAmounts = useMemo(() => { - let selectedResourcesGiveAmounts: { [resourceId: number]: number } = {}; - resourcesGive.forEach((resource) => { - selectedResourcesGiveAmounts[resource.resourceId] = resource.amount; - }); - return selectedResourcesGiveAmounts; - }, [selectedTrade]); - - return ( - -
- ({ resourceId, amount: divideByPrecision(amount) }))} - setCanCarry={setCanCarry} - travelTime={travelTime} - /> -
- - -
-
-
- ); -}; diff --git a/client/src/ui/components/cityview/realm/trade/CreateOffer.tsx b/client/src/ui/components/cityview/realm/trade/CreateOffer.tsx deleted file mode 100644 index 8742a65dd..000000000 --- a/client/src/ui/components/cityview/realm/trade/CreateOffer.tsx +++ /dev/null @@ -1,344 +0,0 @@ -import { ReactComponent as ArrowSeparator } from "@/assets/icons/common/arrow-separator.svg"; -import { getResourceBalance } from "@/hooks/helpers/useResources"; -import { TravelInfo } from "@/ui/components/resources/ResourceWeight"; -import { ONE_MONTH, resources } from "@bibliothecadao/eternum"; -import { useMemo, useState } from "react"; -import { useDojo } from "../../../../../hooks/context/DojoContext"; -import { useRealm } from "../../../../../hooks/helpers/useRealm"; -import useBlockchainStore from "../../../../../hooks/store/useBlockchainStore"; -import useRealmStore from "../../../../../hooks/store/useRealmStore"; -import Button from "../../../../elements/Button"; -import { Headline } from "../../../../elements/Headline"; -import { NumberInput } from "../../../../elements/NumberInput"; -import { ResourceCost } from "../../../../elements/ResourceCost"; -import { SecondaryPopup } from "../../../../elements/SecondaryPopup"; -import { SelectableResource } from "../../../../elements/SelectableResource"; -import { Steps } from "../../../../elements/Steps"; -import { divideByPrecision, multiplyByPrecision } from "../../../../utils/utils"; -import { TradeRealmSelector } from "./TradeRealmSelector"; - -interface CreateOfferPopupProps { - onClose: () => void; - onCreate: () => void; -} - -export const CreateOfferPopup = ({ onClose }: CreateOfferPopupProps) => { - const [step, setStep] = useState(1); - const [selectedResourceIdsGive, setSelectedResourceIdsGive] = useState([]); - const [selectedResourceIdsGet, setSelectedResourceIdsGet] = useState([]); - const [selectedResourcesGiveAmounts, setSelectedResourcesGiveAmounts] = useState>({}); - const [selectedResourcesGetAmounts, setSelectedResourcesGetAmounts] = useState>({}); - const [selectedRealmEntityId, setSelectedRealmEntityId] = useState(); - const [selectedRealmId, setSelectedRealmId] = useState(); - const [canCarry, setCanCarry] = useState(false); - const [isLoading, setIsLoading] = useState(false); - - const { - account: { account }, - setup: { - systemCalls: { create_order }, - }, - } = useDojo(); - - const realmEntityId = useRealmStore((state) => state.realmEntityId); - - const nextBlockTimestamp = useBlockchainStore((state) => state.nextBlockTimestamp); - - const { getRealmEntityIdFromRealmId } = useRealm(); - - const onSelectRealmId = (realmId: bigint) => { - const entityId = getRealmEntityIdFromRealmId(realmId); - entityId && setSelectedRealmEntityId(entityId); - }; - - const createOrder = async () => { - setIsLoading(true); - if (!nextBlockTimestamp) return; - await create_order({ - signer: account, - maker_id: realmEntityId, - maker_gives_resources: selectedResourceIdsGive.flatMap((id) => [ - id, - multiplyByPrecision(selectedResourcesGiveAmounts[id]), - ]), - taker_id: selectedRealmEntityId || 0, - taker_gives_resources: selectedResourceIdsGet.flatMap((id) => [ - id, - multiplyByPrecision(selectedResourcesGetAmounts[id]), - ]), - expires_at: nextBlockTimestamp + ONE_MONTH, - }); - onClose(); - }; - - const canGoToNextStep = useMemo(() => { - if (step === 1) { - return selectedResourceIdsGive.length > 0 && selectedResourceIdsGet.length > 0; - } else if (step === 3) { - return canCarry; - } else { - return true; - } - }, [step, selectedResourceIdsGet, selectedResourceIdsGive, canCarry]); - - return ( - - -
-
Create Offer:
-
-
- -
- {step == 1 && ( - { - setSelectedResourceIdsGive(e); - setSelectedResourcesGiveAmounts(Object.fromEntries(e.map((id) => [id, 1]))); - }} - selectedResourceIdsGet={selectedResourceIdsGet} - setSelectedResourceIdsGet={(e) => { - setSelectedResourceIdsGet(e); - setSelectedResourcesGetAmounts(Object.fromEntries(e.map((id) => [id, 1]))); - }} - /> - )} - {step == 2 && ( - - )} -
-
- - - {!isLoading && ( - - )} - {isLoading && ( - - )} -
-
-
- ); -}; - -const SelectResourcesPanel = ({ - selectedResourceIdsGive, - setSelectedResourceIdsGive, - selectedResourceIdsGet, - setSelectedResourceIdsGet, -}: { - selectedResourceIdsGive: number[]; - setSelectedResourceIdsGive: (selectedResourceIds: number[]) => void; - selectedResourceIdsGet: number[]; - setSelectedResourceIdsGet: (selectedResourceIds: number[]) => void; -}) => { - const { getBalance } = getResourceBalance(); - - const { realmEntityId } = useRealmStore(); - - return ( -
-
- You Give -
- {resources.map(({ id, trait: _name }) => { - const resource = getBalance(realmEntityId, id); - return ( - { - if (selectedResourceIdsGive.includes(id)) { - setSelectedResourceIdsGive(selectedResourceIdsGive.filter((_id) => _id !== id)); - } else { - setSelectedResourceIdsGive([...selectedResourceIdsGive, id]); - } - }} - /> - ); - })} -
-
-
- -
-
- You Get -
- {resources.map(({ id, trait: _name }) => { - const resource = getBalance(realmEntityId, id); - return ( - { - if (selectedResourceIdsGet.includes(id)) { - setSelectedResourceIdsGet(selectedResourceIdsGet.filter((_id) => _id !== id)); - } else { - setSelectedResourceIdsGet([...selectedResourceIdsGet, id]); - } - }} - /> - ); - })} -
-
-
- ); -}; - -const SelectResourcesAmountPanel = ({ - selectedResourceIdsGive, - selectedResourceIdsGet, - selectedResourcesGiveAmounts, - selectedResourcesGetAmounts, - setSelectedResourcesGiveAmounts, - setSelectedResourcesGetAmounts, - selectedRealmId, - setSelectedRealmId, - setCanCarry, -}: { - selectedResourceIdsGive: number[]; - selectedResourceIdsGet: number[]; - selectedResourcesGiveAmounts: Record; - selectedResourcesGetAmounts: Record; - setSelectedResourcesGiveAmounts: (selectedResourcesGiveAmounts: Record) => void; - setSelectedResourcesGetAmounts: (selectedResourcesGetAmounts: Record) => void; - selectedRealmId: bigint | undefined; - setSelectedRealmId: (selectedRealmId: bigint) => void; - setCanCarry: (canCarry: boolean) => void; -}) => { - const { realmEntityId } = useRealmStore(); - - const { getBalance } = getResourceBalance(); - - return ( - <> -
-
- You Give - {selectedResourceIdsGive.map((id) => { - const resource = getBalance(realmEntityId, id); - return ( -
- { - setSelectedResourcesGiveAmounts({ - ...selectedResourcesGiveAmounts, - [id]: Math.min(divideByPrecision(resource?.balance || 0), value), - }); - }} - /> -
- { - setSelectedResourcesGiveAmounts({ - ...selectedResourcesGiveAmounts, - [id]: divideByPrecision(resource?.balance || 0), - }); - }} - resourceId={id} - amount={divideByPrecision(resource?.balance || 0)} - /> -
-
- ); - })} -
-
- -
-
- You Get - {selectedResourceIdsGet.map((id) => { - const resource = getBalance(realmEntityId, id); - - return ( -
- { - setSelectedResourcesGetAmounts({ - ...selectedResourcesGetAmounts, - [id]: value, - }); - }} - /> -
- -
-
- ); - })} -
-
- ({ - resourceId, - amount: selectedResourcesGetAmounts[resourceId], - }))} - setCanCarry={setCanCarry} - /> - - - ); -}; diff --git a/client/src/ui/components/cityview/realm/trade/DirectOffers/DirectOffersExplorerPopup.tsx b/client/src/ui/components/cityview/realm/trade/DirectOffers/DirectOffersExplorerPopup.tsx deleted file mode 100644 index b8563819c..000000000 --- a/client/src/ui/components/cityview/realm/trade/DirectOffers/DirectOffersExplorerPopup.tsx +++ /dev/null @@ -1,292 +0,0 @@ -import { getResourcesUtils } from "@/hooks/helpers/useResources"; -import { - EternumGlobalConfig, - RealmInterface, - ResourcesIds, - findResourceById, - getOrderName, - resources, -} from "@bibliothecadao/eternum"; -import { useDeferredValue, useEffect, useMemo, useState } from "react"; -import useRealmStore from "../../../../../../hooks/store/useRealmStore"; -import useUIStore from "../../../../../../hooks/store/useUIStore"; -import Button from "../../../../../elements/Button"; -import { FilterButton } from "../../../../../elements/FilterButton"; -import { FiltersPanel } from "../../../../../elements/FiltersPanel"; -import { Headline } from "../../../../../elements/Headline"; -import { OnlineStatus } from "../../../../../elements/OnlineStatus"; -import { OrderIcon } from "../../../../../elements/OrderIcon"; -import { ResourceIcon } from "../../../../../elements/ResourceIcon"; -import { SecondaryPopup } from "../../../../../elements/SecondaryPopup"; -import { SortButton, SortInterface } from "../../../../../elements/SortButton"; -import { SortPanel } from "../../../../../elements/SortPanel"; -import TextInput from "../../../../../elements/TextInput"; -import { getRealm } from "../../../../../utils/realms"; -import { - calculateDistance, - currencyIntlFormat, - formatTimeLeft, - formatTimeLeftDaysHoursMinutes, -} from "../../../../../utils/utils"; -import { FastCreateOfferPopup } from "../FastCreateOffer"; - -type DirectOffersExplorerPopupProps = { - onClose: () => void; -}; - -export const DirectOffersExplorerPopup = ({ onClose }: DirectOffersExplorerPopupProps) => { - const [selectedResourceId, setSelectedResourceId] = useState(null); - const [showCreateOffer, setShowCreateOffer] = useState(false); - const [directOfferRealmId, setDirectOfferRealmId] = useState(); - - useEffect(() => {}, []); - - return ( - <> - {showCreateOffer && ( - setShowCreateOffer(false)} - onCreate={() => {}} - /> - )} - - -
-
Marketplace
-
-
- - {selectedResourceId ? ( - { - setDirectOfferRealmId(realmId); - setShowCreateOffer(true); - }} - /> - ) : ( - setSelectedResourceId(id)} /> - )} - -
- - ); -}; - -const SelectResourcePanel = ({ setSelectedResourceId }: { setSelectedResourceId: (id: number) => void }) => { - return ( -
- Choose resource -
- {resources.map((resource) => { - if (resource.id === ResourcesIds.Lords) return; - return ( -
setSelectedResourceId(resource.id)} - className="flex rounded-xl hover:text-lightest hover:bg-black relative flex-col p-2 pb-8 items-center justify-center text-center text-light-pink text-xs" - > - -
{resource.trait}
-
- ); - })} -
-
- ); -}; - -const RealmResourceExplorerPanel = ({ - resourceId, - setSelectedResourceId, - onCreateDirectOffer, -}: { - resourceId: number; - setSelectedResourceId: (resourceId: number | null) => void; - onCreateDirectOffer: (realmId: bigint) => void; -}) => { - const sortingParams = useMemo(() => { - return [ - { label: "Amount", sortKey: "amount", className: "w-[250px]" }, - { label: "Realm", sortKey: "realm", className: "mr-auto" }, - { label: "Travel time", sortKey: "time", className: "ml-auto" }, - ]; - }, []); - - const [activeSort, setActiveSort] = useState({ - sortKey: "number", - sort: "none", - }); - const [nameFilter, setNameFilter] = useState(""); - const deferredNameFilter = useDeferredValue(nameFilter); - - const realmId = useRealmStore((state) => state.realmId); - - // get realms that have that resource - const { getRealmsWithSpecificResource } = getResourcesUtils(); - const realms = getRealmsWithSpecificResource(resourceId, 1000).map((realm) => { - const realmData = getRealm(realm.realmId); - // counterparty - const realmPosition = realmData ? realmData.position : undefined; - // yours - const yourRealmPosition = realmId ? getRealm(realmId)?.position : undefined; - const distance = realmPosition && yourRealmPosition ? calculateDistance(realmPosition, yourRealmPosition) : 0; - return { - ...realm, - realm: realmData, - distance, - }; - }); - - const realmsFilteredByName = useMemo(() => { - return realms.filter( - (realm) => - realm.realm?.name.toLowerCase().includes(deferredNameFilter.toLowerCase()) || - realm.realm?.realmId.toString().includes(deferredNameFilter), - ); - }, [realms, deferredNameFilter]); - - return ( - <> -
-
- - setSelectedResourceId(null)}> - Resource: {findResourceById(resourceId)?.trait} - - - -
- - {sortingParams.map(({ label, sortKey, className }) => ( - { - setActiveSort({ - sortKey: _sortKey, - sort: _sort, - }); - }} - /> - ))} - -
- {realmsFilteredByName - .filter((realm) => realmId !== realm.realmId) - .map(({ realmEntityId, amount, realm, distance }) => ( -
- -
- ))} -
-
- - ); -}; - -type RealmResourceRowProps = { - realmEntityId: bigint; - balance: number; - resourceId: number; - realm: RealmInterface | undefined; - distance: number; - onCreateDirectOffer: (realmId: bigint) => void; -}; - -const RealmResourceRow = ({ - realmEntityId, - balance, - resourceId, - realm, - distance, - onCreateDirectOffer, -}: RealmResourceRowProps) => { - const setTooltip = useUIStore((state) => state.setTooltip); - - const latestActivity = undefined; - - let status: "online" | "recently" | "offline" = "offline"; - - // 86400 = 1 day - // 259200 = 3 days - status = - latestActivity === undefined - ? "offline" - : latestActivity < 86400 - ? "online" - : latestActivity < 259200 - ? "recently" - : "offline"; - - return ( -
-
- - {currencyIntlFormat(balance)} -
-
- setTooltip({ - position: "top", - content: ( - <> -

- {latestActivity !== undefined - ? `${formatTimeLeftDaysHoursMinutes(latestActivity)} ago` - : "No Activity"} -

- - ), - }) - } - onMouseLeave={() => setTooltip(null)} - className="flex mr-auto items-center text-light-pink" - > - - {realm && } - {realm?.name} -
- -
-
{distance.toFixed(0)} km
-
{`(${formatTimeLeft( - (distance / EternumGlobalConfig.speed.donkey) * 3600, - )})`}
- -
-
- ); -}; diff --git a/client/src/ui/components/cityview/realm/trade/FastCreateOffer.tsx b/client/src/ui/components/cityview/realm/trade/FastCreateOffer.tsx deleted file mode 100644 index 2aa82d18e..000000000 --- a/client/src/ui/components/cityview/realm/trade/FastCreateOffer.tsx +++ /dev/null @@ -1,431 +0,0 @@ -import { useDojo } from "@/hooks/context/DojoContext"; -import { getResourceBalance } from "@/hooks/helpers/useResources"; -import { createOffer } from "@/ui/components/navigation/Config"; -import { OSWindow } from "@/ui/components/navigation/OSWindow"; -import { TravelInfo } from "@/ui/components/resources/ResourceWeight"; -import { ONE_MONTH, resources, ResourcesIds } from "@bibliothecadao/eternum"; -import { useEffect, useMemo, useState } from "react"; -import { useRealm } from "../../../../../hooks/helpers/useRealm"; -import useBlockchainStore from "../../../../../hooks/store/useBlockchainStore"; -import useRealmStore from "../../../../../hooks/store/useRealmStore"; -import { usePlayResourceSound } from "../../../../../hooks/useUISound"; -import Button from "../../../../elements/Button"; -import { Headline } from "../../../../elements/Headline"; -import ListSelect from "../../../../elements/ListSelect"; -import { NumberInput } from "../../../../elements/NumberInput"; -import { ResourceCost } from "../../../../elements/ResourceCost"; -import { divideByPrecision, multiplyByPrecision } from "../../../../utils/utils"; -import { TradeRealmSelector } from "./TradeRealmSelector"; - -interface FastCreateOfferPopupProps { - resourceId?: number; - isBuy?: boolean; - marketplaceMode?: boolean; - directOfferRealmId?: bigint; - onClose: () => void; - onCreate: () => void; - show: boolean; -} - -export const FastCreateOfferPopup = ({ - resourceId = 1, - isBuy, - onClose, - marketplaceMode, - directOfferRealmId, - show, -}: FastCreateOfferPopupProps) => { - const [selectedResourceIdsGive, setSelectedResourceIdsGive] = useState([]); - const [selectedResourceIdsGet, setSelectedResourceIdsGet] = useState([]); - const [selectedResourcesGiveAmounts, setSelectedResourcesGiveAmounts] = useState>({}); - const [selectedResourcesGetAmounts, setSelectedResourcesGetAmounts] = useState>({}); - const [canCarry, setCanCarry] = useState(false); - const [selectedRealmId, setSelectedRealmId] = useState(); - const [isLoading, setIsLoading] = useState(false); - - const { - account: { account }, - setup: { - systemCalls: { create_order }, - }, - } = useDojo(); - - const realmEntityId = useRealmStore((state) => state.realmEntityId); - - const nextBlockTimestamp = useBlockchainStore((state) => state.nextBlockTimestamp); - const { getRealmEntityIdFromRealmId } = useRealm(); - - useEffect(() => { - if (isBuy) { - setSelectedResourceIdsGive([ResourcesIds.Lords]); - setSelectedResourceIdsGet([resourceId]); - setSelectedResourcesGiveAmounts({ [ResourcesIds.Lords]: 1 }); - setSelectedResourcesGetAmounts({ [resourceId]: 1 }); - } else { - setSelectedResourceIdsGive([resourceId]); - setSelectedResourceIdsGet([ResourcesIds.Lords]); - setSelectedResourcesGiveAmounts({ [resourceId]: 1 }); - setSelectedResourcesGetAmounts({ [ResourcesIds.Lords]: 1 }); - } - }, [resourceId, isBuy]); - - useEffect(() => { - if (directOfferRealmId) { - setSelectedRealmId(directOfferRealmId); - } - }, [directOfferRealmId]); - - const createOrder = () => { - const selectedRealmEntityId = selectedRealmId ? getRealmEntityIdFromRealmId(selectedRealmId) : 0; - setIsLoading(true); - if (!nextBlockTimestamp) return; - create_order({ - signer: account, - maker_id: realmEntityId, - maker_gives_resources: selectedResourceIdsGive.flatMap((id) => [ - id, - multiplyByPrecision(selectedResourcesGiveAmounts[id]), - ]), - taker_id: selectedRealmEntityId || 0, - taker_gives_resources: selectedResourceIdsGet.flatMap((id) => [ - id, - multiplyByPrecision(selectedResourcesGetAmounts[id]), - ]), - expires_at: nextBlockTimestamp + ONE_MONTH, - }).finally(() => { - setIsLoading(false); - onClose(); - }); - }; - - return ( - -
- -
-
- -
-
- ); -}; - -const SelectResourcesAmountPanel = ({ - selectedResourceIdsGive, - selectedResourceIdsGet, - selectedResourcesGiveAmounts, - selectedResourcesGetAmounts, - setSelectedResourceIdsGive, - setSelectedResourceIdsGet, - setSelectedResourcesGiveAmounts, - setSelectedResourcesGetAmounts, - selectedRealmId, - setSelectedRealmId, - marketplaceMode, - setCanCarry, -}: { - selectedResourceIdsGive: number[]; - selectedResourceIdsGet: number[]; - selectedResourcesGiveAmounts: Record; - selectedResourcesGetAmounts: Record; - setSelectedResourceIdsGive: (selectedResourceIdsGive: number[]) => void; - setSelectedResourceIdsGet: (selectedResourceIdsGet: number[]) => void; - setSelectedResourcesGiveAmounts: (selectedResourcesGiveAmounts: Record) => void; - setSelectedResourcesGetAmounts: (selectedResourcesGetAmounts: Record) => void; - selectedRealmId: bigint | undefined; - setSelectedRealmId: (selectedRealmId: bigint) => void; - marketplaceMode?: boolean; - setCanCarry: (canCarryResources: boolean) => void; -}) => { - const { realmEntityId } = useRealmStore(); - - const { getBalance } = getResourceBalance(); - const { playResourceSound } = usePlayResourceSound(); - - const swapResources = () => { - const tmpGet = [...selectedResourceIdsGet]; - const tmpGive = [...selectedResourceIdsGive]; - const tmpGetAmounts = { ...selectedResourcesGetAmounts }; - const tmpGiveAmounts = { ...selectedResourcesGiveAmounts }; - setSelectedResourceIdsGive(tmpGet); - setSelectedResourceIdsGet(tmpGive); - setSelectedResourcesGiveAmounts(tmpGetAmounts); - setSelectedResourcesGetAmounts(tmpGiveAmounts); - }; - - const unselectedResources = useMemo( - () => - resources.filter((res) => !selectedResourceIdsGive.includes(res.id) && !selectedResourceIdsGet.includes(res.id)), - [selectedResourceIdsGive, selectedResourceIdsGet], - ); - - const addResourceGive = () => { - setSelectedResourceIdsGive([...selectedResourceIdsGive, unselectedResources[0].id]); - setSelectedResourcesGiveAmounts({ - ...selectedResourcesGiveAmounts, - [unselectedResources[0].id]: 1, - }); - playResourceSound(unselectedResources[0].id); - }; - - const addResourceGet = () => { - setSelectedResourceIdsGet([...selectedResourceIdsGet, unselectedResources[0].id]); - setSelectedResourcesGetAmounts({ - ...selectedResourcesGetAmounts, - [unselectedResources[0].id]: 1, - }); - playResourceSound(unselectedResources[0].id); - }; - - return ( - <> -
-
- You Sell - {selectedResourceIdsGive.map((id, index) => { - const resource = getBalance(realmEntityId, id); - let options = [resources.find((res) => res.id === id), ...unselectedResources] as any; - options = options.map((res: any) => { - const bal = getBalance(realmEntityId, res.id); - return { - id: res.id, - label: ( - { - e.preventDefault(); - setSelectedResourcesGiveAmounts({ - ...selectedResourcesGiveAmounts, - [id]: divideByPrecision(bal?.balance || 0), - }); - }} - resourceId={res.id} - amount={divideByPrecision(bal?.balance || 0)} - /> - ), - }; - }); - if (selectedResourceIdsGive.length > 1) { - options = [ - { - id: 0, - label: ( -
-
Remove item
-
- ), - }, - ...options, - ]; - } - return ( -
- { - setSelectedResourcesGiveAmounts({ - ...selectedResourcesGiveAmounts, - [id]: Math.min(divideByPrecision(resource?.balance || 0), value), - }); - }} - /> - {id !== ResourcesIds.Lords || !marketplaceMode ? ( - { - if (value === 0) { - const tmp = [...selectedResourceIdsGive]; - tmp.splice(index, 1); - setSelectedResourceIdsGive(tmp); - const tmpAmounts = { ...selectedResourcesGiveAmounts }; - delete tmpAmounts[id]; - setSelectedResourcesGiveAmounts(tmpAmounts); - return; - } - const tmp = [...selectedResourceIdsGive]; - tmp[index] = value; - playResourceSound(value); - setSelectedResourceIdsGive(tmp); - setSelectedResourcesGiveAmounts({ - ...selectedResourcesGiveAmounts, - [value]: 1, - }); - }} - /> - ) : ( - - )} -
- ); - })} - {!marketplaceMode && ( - - )} -
-
- -
-
- You Buy - {selectedResourceIdsGet.map((id, index) => { - const resource = getBalance(realmEntityId, id); - let options = [resources.find((res) => res.id === id), ...unselectedResources] as any; - options = options.map((res: any) => { - const bal = getBalance(realmEntityId, res.id); - return { - id: res.id, - label: ( - { - e.preventDefault(); - setSelectedResourcesGetAmounts({ - ...selectedResourcesGetAmounts, - [id]: divideByPrecision(bal?.balance || 0), - }); - }} - resourceId={res.id} - amount={divideByPrecision(bal?.balance || 0)} - /> - ), - }; - }); - if (selectedResourceIdsGet.length > 1) { - options = [ - { - id: 0, - label: ( -
-
Remove item
-
- ), - }, - ...options, - ]; - } - return ( -
- { - setSelectedResourcesGetAmounts({ - ...selectedResourcesGetAmounts, - [id]: value, - }); - }} - /> - {id !== ResourcesIds.Lords || !marketplaceMode ? ( - { - if (value === 0) { - const tmp = [...selectedResourceIdsGet]; - tmp.splice(index, 1); - setSelectedResourceIdsGet(tmp); - const tmpAmounts = { ...selectedResourcesGetAmounts }; - delete tmpAmounts[id]; - setSelectedResourcesGetAmounts(tmpAmounts); - return; - } - const tmp = [...selectedResourceIdsGet]; - tmp[index] = value; - playResourceSound(value); - setSelectedResourceIdsGet(tmp); - setSelectedResourcesGetAmounts({ - ...selectedResourcesGetAmounts, - [value]: 1, - }); - }} - /> - ) : ( - - )} -
- ); - })} - {!marketplaceMode && ( - - )} -
-
- ({ - resourceId, - amount: selectedResourcesGetAmounts[resourceId], - }))} - setCanCarry={setCanCarry} - > - {!marketplaceMode && ( - - )} - - ); -}; diff --git a/client/src/ui/components/cityview/realm/trade/Market/MarketOffer.tsx b/client/src/ui/components/cityview/realm/trade/Market/MarketOffer.tsx deleted file mode 100644 index f0b6ac31e..000000000 --- a/client/src/ui/components/cityview/realm/trade/Market/MarketOffer.tsx +++ /dev/null @@ -1,150 +0,0 @@ -import { useEffect, useMemo, useState } from "react"; -import { OrderIcon } from "../../../../../elements/OrderIcon"; -import Button from "../../../../../elements/Button"; -import { ResourceIcon } from "../../../../../elements/ResourceIcon"; -import { MarketInterface, Resource, RoadInterface, findResourceById, orderNameDict } from "@bibliothecadao/eternum"; -import { ReactComponent as RatioIcon } from "@/assets/icons/common/ratio.svg"; -import * as realmsData from "../../../../../../data/geodata/realms.json"; -import { useGetRealm } from "../../../../../../hooks/helpers/useRealm"; -import clsx from "clsx"; -import { currencyFormat } from "../../../../../utils/utils"; -import useUIStore from "../../../../../../hooks/store/useUIStore"; -import { useCaravan } from "../../../../../../hooks/helpers/useCaravans"; -import useRealmStore from "../../../../../../hooks/store/useRealmStore"; -import { useRoads } from "../../../../../../hooks/helpers/useRoads"; -import { useTrade } from "../../../../../../hooks/helpers/useTrade"; - -type TradeOfferProps = { - roads: RoadInterface[]; - marketOffer: MarketInterface; - onAccept: () => void; - onBuildRoad: () => void; -}; - -export const MarketOffer = ({ marketOffer, roads, onAccept, onBuildRoad }: TradeOfferProps) => { - const { makerId, takerGets: resourcesGet, makerGets: resourcesGive, ratio } = marketOffer; - - let { realm: makerRealm } = useGetRealm(marketOffer.makerId); - const setTooltip = useUIStore((state) => state.setTooltip); - const realmEntityId = useRealmStore((state) => state.realmEntityId); - - const [isLoading, setIsLoading] = useState(false); - - const { calculateDistance } = useCaravan(); - const { getHasRoad } = useRoads(); - const { canAcceptOffer } = useTrade(); - - const distance = useMemo(() => { - return calculateDistance(makerId, realmEntityId) || 0; - }, [makerId, realmEntityId]); - - const hasRoad = useMemo(() => { - return getHasRoad(realmEntityId, makerId); - }, [realmEntityId, makerId, roads]); - - const canAccept = useMemo(() => { - return canAcceptOffer({ realmEntityId, resourcesGive }); - }, [realmEntityId, resourcesGive]); - - useEffect(() => { - setIsLoading(false); - }, [marketOffer]); - - return ( -
-
- {makerRealm && ( -
- {/* // order of the order maker */} - {makerRealm.order && } - {realmsData["features"][Number(makerRealm.realmId) - 1]?.name || ""} -
- )} -
-
{`${distance.toFixed(0)} km`}
- -
-
-
-
-
- {resourcesGive && - resourcesGive.map(({ resourceId, amount }) => ( -
- - {currencyFormat(amount, 0)} -
- ))} -
-
- - {resourcesGive && resourcesGet && ratio.toFixed(2)} -
-
- {resourcesGet && - resourcesGet.map(({ resourceId, amount }) => ( -
- - {currencyFormat(amount, 0)} -
- ))} -
-
-
- - {!canAccept && ( -
- Insufficient resources -
- )} -
-
-
- ); -}; - -export const calculateRatio = (resourcesGive: Resource[], resourcesGet: Resource[]) => { - let quantityGive = 0; - for (let i = 0; i < resourcesGive.length; i++) { - quantityGive += resourcesGive[i].amount; - } - let quantityGet = 0; - for (let i = 0; i < resourcesGet.length; i++) { - quantityGet += resourcesGet[i].amount; - } - return quantityGet / quantityGive; -}; diff --git a/client/src/ui/components/cityview/realm/trade/Market/MarketPanel.tsx b/client/src/ui/components/cityview/realm/trade/Market/MarketPanel.tsx deleted file mode 100644 index 1ac1caf69..000000000 --- a/client/src/ui/components/cityview/realm/trade/Market/MarketPanel.tsx +++ /dev/null @@ -1,231 +0,0 @@ -import { ReactComponent as Refresh } from "@/assets/icons/common/refresh.svg"; -import { MarketInterface } from "@bibliothecadao/eternum"; -import { useEffect, useMemo, useRef, useState } from "react"; -import { useGetRoads } from "../../../../../../hooks/helpers/useRoads"; -import { sortTrades, useTrade } from "../../../../../../hooks/helpers/useTrade"; -import useMarketStore from "../../../../../../hooks/store/useMarketStore"; -import useRealmStore from "../../../../../../hooks/store/useRealmStore"; -import useUIStore from "../../../../../../hooks/store/useUIStore"; -import Button from "../../../../../elements/Button"; -import { Checkbox } from "../../../../../elements/Checkbox"; -import { FiltersPanel } from "../../../../../elements/FiltersPanel"; -import { SortButton, SortInterface } from "../../../../../elements/SortButton"; -import { SortPanel } from "../../../../../elements/SortPanel"; -import { DirectOffersExplorerPopup } from "../DirectOffers/DirectOffersExplorerPopup"; -import { RoadBuildPopup } from "../Roads/RoadBuildPopup"; -import { hasResources } from "../utils"; -import { MarketOffer } from "./MarketOffer"; -import { OrdersFilter } from "./OrdersFilter"; -import { ResourceFilter } from "./ResourceFilter"; - -type MarketPanelProps = { - directOffers: boolean; -}; - -export const MarketPanel = ({ directOffers }: MarketPanelProps) => { - const [showCreateOffer, setShowCreateOffer] = useState(false); - const [showMarketplace, setShowMarketplace] = useState(false); - const [showDirectOffersExplorer, setShowDirectOffersExplorer] = useState(false); - const [selectedTrade, setSelectedTrade] = useState(undefined); - const [selectedBuyResources, setSelectedBuyResources] = useState([]); - const [selectedSellResources, setSelectedSellResources] = useState([]); - const [selectedOrders, setSelectedOrders] = useState([]); - const [canAcceptFilterActive, setCanAcceptFilterActive] = useState(true); - const [buildRoadToEntityId, setBuildRoadToEntityId] = useState(undefined); - - const realmEntityId = useRealmStore((state) => state.realmEntityId); - const { canAcceptOffer } = useTrade(); - - const sortingParams = useMemo(() => { - return [ - { label: "Realm", sortKey: "realm" }, - { label: "Give", sortKey: "give", className: "ml-4" }, - { label: "Exchange rate", sortKey: "ratio", className: "ml-auto mr-4" }, - { label: "Get", sortKey: "get", className: "ml-auto mr-4" }, - { label: "Travel distance", sortKey: "distance", className: "ml-auto mr-4" }, - ]; - }, []); - - const [activeSort, setActiveSort] = useState({ - sortKey: "number", - sort: "none", - }); - - const setTooltip = useUIStore((state) => state.setTooltip); - - const market = directOffers - ? useMarketStore((state) => state.directOffers) - : // filter out your own offers - useMarketStore((state) => state.generalMarket).filter((offer) => offer.makerId !== realmEntityId); - - // const refreshMarket = useMarketStore((state) => state.refreshMarket); - - const [visibleOffersCount, setVisibleOffersCount] = useState(10); // new state to track the number of visible offers - - const loadMoreOffers = () => { - setVisibleOffersCount((prevCount) => prevCount + 10); - }; - - // Use an intersection observer to detect when the sentinel element is visible - const sentinelRef = useRef(null); - - // rerender if new roads - const { roads } = useGetRoads(realmEntityId); - - const renderedMarketOffers = useMemo(() => { - if (!market) return null; - - return ( -
- {sortTrades(market, activeSort) - .filter((offer: any) => { - return canAcceptFilterActive ? canAcceptOffer({ realmEntityId, resourcesGive: offer.makerGets }) : true; - }) - .filter((offer: any) => { - return hasResources(offer.takerGets, selectedBuyResources); - }) - .filter((offer: any) => { - return hasResources(offer.makerGets, selectedSellResources); - }) - .filter((offer: any) => { - return selectedOrders.length === 0 || selectedOrders.includes(offer.makerOrder); - }) - .slice(0, visibleOffersCount) // modify this line to control the number of displayed offers - .map((trade: any) => ( - setSelectedTrade(trade)} - onBuildRoad={() => setBuildRoadToEntityId(trade.makerId)} - /> - ))} -
{/* sentinel element */} -
- ); - }, [market, activeSort, visibleOffersCount]); // add visibleOffersCount to dependencies - - useEffect(() => { - const observer = new IntersectionObserver((entries) => { - if (entries[0].isIntersecting) { - loadMoreOffers(); - } - }); - - if (sentinelRef.current) { - observer.observe(sentinelRef.current); - } - - return () => { - if (sentinelRef.current) { - observer.unobserve(sentinelRef.current); - } - }; - }, []); - - return ( - <> - {/* {showCreateOffer && setShowCreateOffer(false)} onCreate={() => {}} />} */} - {showDirectOffersExplorer && setShowDirectOffersExplorer(false)} />} - {buildRoadToEntityId !== undefined && ( - setBuildRoadToEntityId(undefined)} toEntityId={buildRoadToEntityId} /> - )} - {/* {selectedTrade && ( - { - setSelectedTrade(undefined); - }} - selectedTrade={selectedTrade} - /> - )} */} -
-
- - - Sell Resources - - - Buy Resources - - - {(selectedBuyResources.length > 0 || selectedSellResources.length > 0 || selectedOrders.length > 0) && ( - - )} - -
-
setCanAcceptFilterActive(!canAcceptFilterActive)} - > - -
Accept
-
- {!directOffers && ( - refreshMarket()} - // todo: find a way to refresh asynchronously - onClick={() => {}} - onMouseLeave={() => setTooltip(null)} - onMouseEnter={() => - setTooltip({ - position: "bottom", - content: ( - <> -

Click here to refresh the marketplace

- - ), - }) - } - className="text-gold cursor-pointer" - >
- )} -
-
- - {sortingParams.map(({ label, sortKey, className }) => ( - { - setActiveSort({ - sortKey: _sortKey, - sort: _sort, - }); - }} - /> - ))} - - {renderedMarketOffers} -
- {!directOffers && ( - <> - - - - )} - {directOffers && ( - - )} -
-
- - ); -}; diff --git a/client/src/ui/components/cityview/realm/trade/Market/OrdersFilter.tsx b/client/src/ui/components/cityview/realm/trade/Market/OrdersFilter.tsx deleted file mode 100644 index f60f3a428..000000000 --- a/client/src/ui/components/cityview/realm/trade/Market/OrdersFilter.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import { useState } from "react"; -import { FilterButton } from "../../../../../elements/FilterButton"; -import { SecondaryPopup } from "../../../../../elements/SecondaryPopup"; -import { getOrderName, orders } from "@bibliothecadao/eternum"; -import Button from "../../../../../elements/Button"; -import { OrderIcon } from "../../../../../elements/OrderIcon"; -import clsx from "clsx"; - -type OrdersFilterProps = { - selectedOrders: number[]; - setSelectedOrders: (orders: number[]) => void; -}; - -export const OrdersFilter = ({ selectedOrders, setSelectedOrders }: OrdersFilterProps) => { - const [popupOpened, setPopupOpened] = useState(false); - - const selectOrder = (order: number) => { - if (selectedOrders.includes(order)) { - setSelectedOrders(selectedOrders.filter((o) => o !== order)); - } else { - setSelectedOrders([...selectedOrders, order]); - } - }; - - return ( - <> - setPopupOpened(!popupOpened)}> - Orders - - {popupOpened && ( - - setPopupOpened(false)}> -
-
Orders:
- {selectedOrders.map((order, index) => ( - - ))} - {selectedOrders.length > 0 && ( - - )} -
-
- -
- {orders - // remove order of gods - .filter((order) => order.orderId !== 17) - .map((order, index) => ( -
selectOrder(order.orderId)} - > - -
{order.orderName}
-
- ))} -
-
- -
-
-
- )} - - ); -}; diff --git a/client/src/ui/components/cityview/realm/trade/Market/ResourceFilter.tsx b/client/src/ui/components/cityview/realm/trade/Market/ResourceFilter.tsx deleted file mode 100644 index f34476af0..000000000 --- a/client/src/ui/components/cityview/realm/trade/Market/ResourceFilter.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import { useState } from "react"; -import { FilterButton } from "../../../../../elements/FilterButton"; -import { SecondaryPopup } from "../../../../../elements/SecondaryPopup"; -import { resources } from "@bibliothecadao/eternum"; -import { SelectBox } from "../../../../../elements/SelectBox"; -import { ResourceIcon } from "../../../../../elements/ResourceIcon"; -import Button from "../../../../../elements/Button"; - -type ResourceFilterProps = { - children: React.ReactNode; - selectedResources: number[]; - setSelectedResources: (resources: number[]) => void; -}; - -export const ResourceFilter = ({ selectedResources, setSelectedResources, children }: ResourceFilterProps) => { - const [popupOpened, setPopupOpened] = useState(false); - - const selectResource = (resource: number) => { - if (selectedResources.includes(resource)) { - setSelectedResources(selectedResources.filter((r) => r !== resource)); - } else { - setSelectedResources([...selectedResources, resource]); - } - }; - - return ( - <> - setPopupOpened(!popupOpened)}> - {children} - - {popupOpened && ( - - setPopupOpened(false)}> -
-
{children}
- {selectedResources.map((selectedResource, index) => ( - resource.id === selectedResource)?.trait || ""} - /> - ))} - {selectedResources.length > 0 && ( - - )} -
-
- -
- {resources.map((resource, index) => ( - selectResource(resource.id)} - > -
- - {resource.trait} -
-
- ))} -
-
- -
-
-
- )} - - ); -}; diff --git a/client/src/ui/components/cityview/realm/trade/MyOffers/MyOffer.tsx b/client/src/ui/components/cityview/realm/trade/MyOffers/MyOffer.tsx deleted file mode 100644 index 3afde3326..000000000 --- a/client/src/ui/components/cityview/realm/trade/MyOffers/MyOffer.tsx +++ /dev/null @@ -1,166 +0,0 @@ -import { useEffect, useMemo, useState } from "react"; -import { OrderIcon } from "../../../../../elements/OrderIcon"; -import Button from "../../../../../elements/Button"; -import { ResourceIcon } from "../../../../../elements/ResourceIcon"; -import { MarketInterface, RoadInterface, findResourceById, orderNameDict } from "@bibliothecadao/eternum"; -import { ReactComponent as RatioIcon } from "../@/assets/icons/common/ratio.svg"; -import { useDojo } from "../../../../../../hooks/context/DojoContext"; -import * as realmsData from "../../../../../../data/geodata/realms.json"; -import { useGetRealm } from "../../../../../../hooks/helpers/useRealm"; -import { currencyFormat } from "../../../../../utils/utils"; -import useUIStore from "../../../../../../hooks/store/useUIStore"; -import { useCaravan } from "../../../../../../hooks/helpers/useCaravans"; -import { useRoads } from "../../../../../../hooks/helpers/useRoads"; -import useRealmStore from "../../../../../../hooks/store/useRealmStore"; - -type TradeOfferProps = { - myOffer: MarketInterface; - roads: RoadInterface[]; - onBuildRoad: () => void; -}; - -export const MyOffer = ({ myOffer, roads, onBuildRoad }: TradeOfferProps) => { - // todo: make hasRoad reactive - // @note: in myoffers, player is always maker, so resourcesGet is always makerGets, resourcesGive is always takerGets - const { takerId, makerGets: resourcesGet, takerGets: resourcesGive, ratio } = myOffer; - - const realmEntityId = useRealmStore((state) => state.realmEntityId); - - const [isLoading, setIsLoading] = useState(false); - const setTooltip = useUIStore((state) => state.setTooltip); - - const { calculateDistance } = useCaravan(); - const { getHasRoad } = useRoads(); - - const distance = useMemo(() => { - return calculateDistance(takerId, realmEntityId) || 0; - }, [takerId, realmEntityId]); - - const hasRoad = useMemo(() => { - return getHasRoad(realmEntityId, takerId); - }, [realmEntityId, takerId, roads]); - - useEffect(() => { - setIsLoading(false); - }, [myOffer]); - - const { - setup: { - systemCalls: { cancel_order }, - }, - account: { account }, - } = useDojo(); - - const onCancel = async () => { - // status 2 = cancel - setIsLoading(true); - cancel_order({ - signer: account, - trade_id: myOffer.tradeId, - return_resources: resourcesGive.flatMap(({ resourceId, amount }) => [resourceId, amount]), - }); - }; - - let { realm: takerRealm } = useGetRealm(takerId); - - const getResourceTrait = useMemo(() => { - return (resourceId: number) => findResourceById(resourceId)?.trait as any; - }, []); - - let timeLeft = formatTimeLeft(myOffer.expiresAt - Date.now() / 1000); - - return ( -
-
- {takerRealm ? ( -
- {/* order of the order maker */} - {takerRealm.order && } - {realmsData["features"][Number(takerRealm.realmId) - 1]?.name || ""} -
- ) : ( -
- )} - {!takerRealm &&
{`Expires in ${timeLeft}`}
} - {takerRealm && ( -
-
{`${distance.toFixed(0)} km`}
- -
- )} -
-
-
-
- {resourcesGive && - resourcesGive.map(({ resourceId, amount }) => ( -
- - {currencyFormat(amount, 0)} -
- ))} -
-
- - {(1 / ratio).toFixed(2)} -
-
- {resourcesGet && - resourcesGet.map(({ resourceId, amount }) => ( -
- - {currencyFormat(amount, 0)} -
- ))} -
-
- -
-
- ); -}; - -const formatTimeLeft = (seconds: number) => { - const days = Math.floor(seconds / 86400); - const hours = Math.floor((seconds % 86400) / 3600); - const minutes = Math.floor((seconds % 3600) / 60); - - if (days > 0) { - return `${days} days`; - } else { - return `${hours}h:${minutes}m`; - } -}; diff --git a/client/src/ui/components/cityview/realm/trade/Roads/Road.tsx b/client/src/ui/components/cityview/realm/trade/Roads/Road.tsx deleted file mode 100644 index ba253176c..000000000 --- a/client/src/ui/components/cityview/realm/trade/Roads/Road.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import { useMemo } from "react"; -import { OrderIcon } from "../../../../../elements/OrderIcon"; -import Button from "../../../../../elements/Button"; -import { RoadInterface, orderNameDict } from "@bibliothecadao/eternum"; -import clsx from "clsx"; - -type RoadProps = { - road: RoadInterface; - onAddUsage: () => void; -}; - -export const Road = (props: RoadProps) => { - const { - road: { startRealmName, startRealmOrder, destinationRealmName, destinationRealmOrder, usageLeft }, - onAddUsage, - } = props; - - const canBuild = useMemo(() => { - return usageLeft === 0; - }, [usageLeft]); - - return ( -
-
- {startRealmName && ( -
- {/* // order of the order maker */} - {startRealmOrder && } - {startRealmName} -
- )} -
Usages left: {usageLeft}
-
-
- {destinationRealmName && ( - <> - Road to{" "} - {destinationRealmOrder && ( - - )} - {destinationRealmName} - - )} -
- - {!canBuild && ( -
Can only add when usage is 0
- )} -
-
-
- ); -}; diff --git a/client/src/ui/components/cityview/realm/trade/Roads/RoadBuildPopup.tsx b/client/src/ui/components/cityview/realm/trade/Roads/RoadBuildPopup.tsx deleted file mode 100644 index aaf51eadf..000000000 --- a/client/src/ui/components/cityview/realm/trade/Roads/RoadBuildPopup.tsx +++ /dev/null @@ -1,148 +0,0 @@ -import { useEffect, useMemo, useState } from "react"; -import { SecondaryPopup } from "../../../../../elements/SecondaryPopup"; -import Button from "../../../../../elements/Button"; -import { Headline } from "../../../../../elements/Headline"; -import { ResourceCost } from "../../../../../elements/ResourceCost"; -import { NumberInput } from "../../../../../elements/NumberInput"; -import useRealmStore from "../../../../../../hooks/store/useRealmStore"; -import { useDojo } from "../../../../../../hooks/context/DojoContext"; -import { getComponentValue } from "@dojoengine/recs"; -import { divideByPrecision, getEntityIdFromKeys } from "../../../../../utils/utils"; -import { useGetRealm } from "../../../../../../hooks/helpers/useRealm"; -import * as realmsData from "../../../../../../data/geodata/realms.json"; -import { ROAD_COST_PER_USAGE } from "@bibliothecadao/eternum"; - -type RoadBuildPopupProps = { - toEntityId: bigint; - onClose: () => void; -}; - -export const RoadBuildPopup = ({ toEntityId, onClose }: RoadBuildPopupProps) => { - const { - setup: { - components: { Resource }, - systemCalls: { create_road }, - }, - account: { account }, - } = useDojo(); - - const [canBuild, setCanBuild] = useState(true); - const [usageAmount, setUsageAmount] = useState(2); - - let realmEntityId = useRealmStore((state) => state.realmEntityId); - - // @ts-ignore - const { realm } = useGetRealm(realmEntityId); - const { realm: toRealm } = useGetRealm(toEntityId); - - // TODO: get info from contract config file - // calculate the costs of building/buying tools - const costResources = useMemo(() => { - return ROAD_COST_PER_USAGE.map(({ resourceId, amount }) => ({ resourceId, amount: amount * usageAmount })); - }, [usageAmount]); - - const onBuild = () => { - if (realm && toRealm) { - const start_position = realm.position; - const end_position = toRealm.position; - create_road({ - signer: account, - creator_id: realmEntityId, - start_coord: start_position, - end_coord: end_position, - usage_count: usageAmount, - }); - onClose(); - } - }; - - useEffect(() => { - // Assume can build initially - let canBuild = true; - - // Check each resource requirement - costResources.forEach(({ resourceId, amount }) => { - const realmResource = getComponentValue( - Resource, - getEntityIdFromKeys([BigInt(realmEntityId), BigInt(resourceId)]), - ); - - // If any resource is not sufficient, set canBuild to false - if (!realmResource || realmResource.balance < amount) { - canBuild = false; - } - }); - - // Update state based on the final canBuild value - setCanBuild(canBuild); - }, [costResources]); - - return ( - - -
-
Build road:
-
-
- -
- {toRealm && ( - Build road to {toRealm && realmsData["features"][Number(toRealm.realmId - 1n)]?.name} - )} -
- -
-
Price:
-
- {costResources.map(({ resourceId, amount }) => ( - - ))} -
-
-
-
-
-
-
Amount
- -
-
-
- - - -
- {!canBuild &&
Insufficient resources
} -
-
-
-
- ); -}; diff --git a/client/src/ui/components/cityview/realm/trade/Roads/RoadRealmSelector.tsx b/client/src/ui/components/cityview/realm/trade/Roads/RoadRealmSelector.tsx deleted file mode 100644 index 59a982c07..000000000 --- a/client/src/ui/components/cityview/realm/trade/Roads/RoadRealmSelector.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import { useEffect, useState } from "react"; -import useRealmStore from "../../../../../../hooks/store/useRealmStore"; -import { useDojo } from "../../../../../../hooks/context/DojoContext"; -import { Has, getComponentValue, runQuery } from "@dojoengine/recs"; -import { SelectableRealmInterface, getOrderName } from "@bibliothecadao/eternum"; -import { useGetRoads, useRoads } from "../../../../../../hooks/helpers/useRoads"; -import { useRealm } from "../../../../../../hooks/helpers/useRealm"; -import { useCaravan } from "../../../../../../hooks/helpers/useCaravans"; -import { getRealm } from "../../../../../utils/realms"; -import { RealmList } from "../../RealmList"; - -export const RoadRealmSelector = ({ - selectedRealmEntityId, - setSelectedRealmEntityId, -}: { - selectedRealmEntityId: bigint | undefined; - setSelectedRealmEntityId: (selectRealmEntityId: bigint) => void; -}) => { - const { - setup: { - components: { Realm }, - }, - } = useDojo(); - - const { getRealmEntityIdFromRealmId, getRealmAddressName } = useRealm(); - - const [selectableRealms, setSelectableRealms] = useState([]); - - const realmId = useRealmStore((state) => state.realmId); - const realmEntityId = useRealmStore((state) => state.realmEntityId); - - const { calculateDistance } = useCaravan(); - - const { getHasRoad } = useRoads(); - - const { roads } = useGetRoads(realmEntityId); - - useEffect(() => { - const buildSelectableRealms = () => { - let entityIds = runQuery([Has(Realm)]); - let realms = Array.from(entityIds) - .map((entityId) => { - const realm = getComponentValue(Realm, entityId); - const hasRoad = getHasRoad(realmEntityId, realm?.entity_id); - if (realm && !hasRoad) { - const realmData = getRealm(realm.realm_id); - if (!realmData) return undefined; - const { name, order, realmId: takerRealmId } = realmData; - const takerEntityId = getRealmEntityIdFromRealmId(takerRealmId); - const distance = takerEntityId ? (calculateDistance(realmEntityId, takerEntityId) ?? 0) : 0; - const addressName = takerEntityId ? getRealmAddressName(takerEntityId) : ""; - return { - entityId: realm.entity_id, - realmId: realm.realm_id, - name, - order: getOrderName(order), - distance, - addressName, - }; - } - }) - .filter((realm) => realm && realm.realmId !== realmId) as SelectableRealmInterface[]; - setSelectableRealms(realms); - }; - buildSelectableRealms(); - }, [roads]); - - return ( - - ); -}; diff --git a/client/src/ui/components/cityview/realm/trade/Roads/RoadsPanel.tsx b/client/src/ui/components/cityview/realm/trade/Roads/RoadsPanel.tsx deleted file mode 100644 index d71ae251e..000000000 --- a/client/src/ui/components/cityview/realm/trade/Roads/RoadsPanel.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import React, { useMemo, useState } from "react"; -import { Road } from "./Road"; -import { RoadBuildPopup } from "./RoadBuildPopup"; -import useRealmStore from "../../../../../../hooks/store/useRealmStore"; -import { useGetRoads } from "../../../../../../hooks/helpers/useRoads"; -import { SortPanel } from "../../../../../elements/SortPanel"; -import { SortButton, SortInterface } from "../../../../../elements/SortButton"; -import { FilterButton } from "../../../../../elements/FilterButton"; -import { FiltersPanel } from "../../../../../elements/FiltersPanel"; -import { RoadRealmSelector } from "./RoadRealmSelector"; - -type RoadsPanelProps = {} & React.HTMLAttributes; - -// @ts-ignore -export const RoadsPanel = (props: RoadsPanelProps) => { - const [activeFilter, setActiveFilter] = useState(false); - const [activeSort, setActiveSort] = useState({ - sortKey: "number", - sort: "none", - }); - - const [buildRoadToEntityId, setBuildRoadToEntityId] = useState(undefined); - - const realmEntityId = useRealmStore((state) => state.realmEntityId); - - const { roads } = useGetRoads(realmEntityId); - - const sortingParams = useMemo(() => { - return [ - { label: "Realm", sortKey: "realm" }, - { label: "Usage Left", sortKey: "usage", className: "" }, - ]; - }, []); - - const onClose = () => { - setBuildRoadToEntityId(undefined); - }; - - return ( - <> - - - setActiveFilter(!activeFilter)}> - Filter - - - - {sortingParams.map(({ label, sortKey, className }) => ( - { - setActiveSort({ - sortKey: _sortKey, - sort: _sort, - }); - }} - /> - ))} - - {buildRoadToEntityId && } -
- {roads - // filter out roads that are not connected to a realm - .filter((road) => road.destinationRealmName !== "") - .map((road) => ( - setBuildRoadToEntityId(road.destinationEntityId)} /> - ))} -
- - ); -}; diff --git a/client/src/ui/components/cityview/realm/trade/TradeRealmSelector.tsx b/client/src/ui/components/cityview/realm/trade/TradeRealmSelector.tsx deleted file mode 100644 index 82bf17f11..000000000 --- a/client/src/ui/components/cityview/realm/trade/TradeRealmSelector.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import { useEffect, useState } from "react"; -import useRealmStore from "../../../../../hooks/store/useRealmStore"; -import { useDojo } from "../../../../../hooks/context/DojoContext"; -import { Has, getComponentValue, runQuery } from "@dojoengine/recs"; -import { RealmList } from "../RealmList"; -import { SelectableRealmInterface, getOrderName } from "@bibliothecadao/eternum"; -import { useRealm } from "../../../../../hooks/helpers/useRealm"; -import { useCaravan } from "../../../../../hooks/helpers/useCaravans"; -import { getRealm } from "../../../../utils/realms"; - -export const TradeRealmSelector = ({ - setSelectedRealmId, -}: { - selectedRealmId: bigint | undefined; - setSelectedRealmId: (selectedRealmId: bigint) => void; -}) => { - const { - setup: { - components: { Realm }, - }, - } = useDojo(); - - const { getRealmAddressName, getRealmIdFromRealmEntityId, getRealmEntityIdFromRealmId } = useRealm(); - const { realmId, realmEntityId } = useRealmStore(); - const { calculateDistance } = useCaravan(); - - const [selectableRealms, setSelectableRealms] = useState([]); - const [selectedRealmEntityId, setSelectedRealmEntityId] = useState(); - - useEffect(() => { - if (selectedRealmEntityId) { - const realmId = getRealmIdFromRealmEntityId(selectedRealmEntityId); - if (realmId) { - setSelectedRealmId(realmId); - } - } - }, [selectedRealmEntityId]); - - useEffect(() => { - const buildSelectableRealms = () => { - let entityIds = runQuery([Has(Realm)]); - let realms = Array.from(entityIds) - .map((entityId) => { - const realm = getComponentValue(Realm, entityId); - if (realm) { - const realmData = getRealm(realm.realm_id); - if (!realmData) return undefined; - const { name, order, realmId: takerRealmId } = realmData; - const takerEntityId = getRealmEntityIdFromRealmId(takerRealmId); - const distance = takerEntityId ? (calculateDistance(realmEntityId, takerEntityId) ?? 0) : 0; - const addressName = takerEntityId ? getRealmAddressName(takerEntityId) : ""; - return { - entityId: realm.entity_id, - realmId: realm.realm_id, - name, - order: getOrderName(order), - distance, - addressName, - }; - } - }) - .filter((realm) => realm && realm.realmId !== realmId) as SelectableRealmInterface[]; - setSelectableRealms(realms); - }; - buildSelectableRealms(); - }, []); - - return ( - - ); -}; diff --git a/client/src/ui/components/cityview/realm/trade/utils.tsx b/client/src/ui/components/cityview/realm/trade/utils.tsx deleted file mode 100644 index 735624036..000000000 --- a/client/src/ui/components/cityview/realm/trade/utils.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import { Resource, WEIGHTS } from "@bibliothecadao/eternum"; - -export const getTotalResourceWeight = (resources: (Resource | undefined)[]) => { - return resources.reduce( - (total, resource) => total + (resource ? resource.amount * WEIGHTS[resource.resourceId] || 0 : 0), - 0, - ); -}; - -export function hasResources(resources: Resource[], selectedBuyResources: number[]) { - if (selectedBuyResources.length > 0) { - // Check if every selected resource is in takerGets - const allSelectedInTakerGets = selectedBuyResources.every((selectedResource) => - resources.some((resource) => resource.resourceId === selectedResource), - ); - - // Check if takerGets contains at least one of the selected resources - const atLeastOneSelectedInTakerGets = resources.some((resource) => - selectedBuyResources.includes(resource.resourceId), - ); - - return allSelectedInTakerGets && atLeastOneSelectedInTakerGets; - } else { - return true; - } -} diff --git a/client/src/ui/components/construction/BuildArea.tsx b/client/src/ui/components/construction/BuildArea.tsx index 97814b160..33a3f6a2e 100644 --- a/client/src/ui/components/construction/BuildArea.tsx +++ b/client/src/ui/components/construction/BuildArea.tsx @@ -7,7 +7,7 @@ import { useEffect, useMemo } from "react"; import { ExistingBuildings, ModelsIndexes } from "./ExistingBuildings"; import { BuildingType } from "@bibliothecadao/eternum"; -export interface OriginalModels { +interface OriginalModels { [key: number | string]: THREE.Group; } diff --git a/client/src/ui/components/construction/ExistingBuildings.tsx b/client/src/ui/components/construction/ExistingBuildings.tsx index c7a08f73d..91aa58ca6 100644 --- a/client/src/ui/components/construction/ExistingBuildings.tsx +++ b/client/src/ui/components/construction/ExistingBuildings.tsx @@ -8,7 +8,7 @@ import { soundSelector, useUiSounds } from "@/hooks/useUISound"; import { BaseThreeTooltip, Position } from "@/ui/elements/BaseThreeTooltip"; import Button from "@/ui/elements/Button"; import { ResourceIdToMiningType, ResourceMiningTypes, getUIPositionFromColRow } from "@/ui/utils/utils"; -import { BuildingStringToEnum, BuildingType, ResourcesIds, biomes } from "@bibliothecadao/eternum"; +import { BuildingStringToEnum, BuildingType, ID, ResourcesIds, biomes } from "@bibliothecadao/eternum"; import { useEntityQuery } from "@dojoengine/react"; import { Has, HasValue, NotValue, getComponentValue } from "@dojoengine/recs"; import { useAnimations, useGLTF, useHelper } from "@react-three/drei"; @@ -30,7 +30,6 @@ export enum ModelsIndexes { Storehouse = BuildingType.Storehouse, Bank = BuildingType.Bank, FragmentMine = BuildingType.FragmentMine, - Settlement = 20, Hyperstructure = 21, UnfinishedHyperstructure = 22, } @@ -66,8 +65,8 @@ export const ExistingBuildings = () => { ); const builtBuildings = useEntityQuery([ Has(Building), - HasValue(Building, { outer_col: BigInt(globalHex.col), outer_row: BigInt(globalHex.row) }), - NotValue(Building, { entity_id: 0n }), + HasValue(Building, { outer_col: globalHex.col, outer_row: globalHex.row }), + NotValue(Building, { entity_id: 0 }), ]); useEffect(() => { @@ -177,7 +176,7 @@ export const MiddleBuilding = ({ hexType }: { hexType: HexType }) => { return null; }; -export const BuiltBuilding = ({ +const BuiltBuilding = ({ position, models, buildingCategory, @@ -300,7 +299,7 @@ const HoverBuilding = ({ }: { destroyButton: React.ReactNode; buildingType: BuildingType; - entityId: bigint; + entityId: ID; name?: string; resource?: ResourcesIds; }) => { diff --git a/client/src/ui/components/construction/GroundGrid.tsx b/client/src/ui/components/construction/GroundGrid.tsx index 1e1ba5d11..454a210d6 100644 --- a/client/src/ui/components/construction/GroundGrid.tsx +++ b/client/src/ui/components/construction/GroundGrid.tsx @@ -117,15 +117,7 @@ const mainColor = new THREE.Color(0.21389107406139374, 0.14227265119552612, 0.06 const mainMaterial = new THREE.MeshStandardMaterial({ color: mainColor }); const invisibleMaterial = new THREE.MeshStandardMaterial({ color: mainColor, transparent: true, opacity: 0 }); -export const Hexagon = ({ - position, - onClick, - onPointerEnter, -}: { - position: any; - onClick: any; - onPointerEnter: any; -}) => { +const Hexagon = ({ position, onClick, onPointerEnter }: { position: any; onClick: any; onPointerEnter: any }) => { return ( @@ -161,7 +153,7 @@ const EmptyCell = ({ position }: { position: any }) => { ); }; -export const generateHexPositions = () => { +const generateHexPositions = () => { const color = new THREE.Color("gray"); const center = HEXCEPTION_CENTER; const RADIUS = 4; diff --git a/client/src/ui/components/construction/SelectPreviewBuilding.tsx b/client/src/ui/components/construction/SelectPreviewBuilding.tsx index f9f0ed85a..0b428aa92 100644 --- a/client/src/ui/components/construction/SelectPreviewBuilding.tsx +++ b/client/src/ui/components/construction/SelectPreviewBuilding.tsx @@ -10,6 +10,7 @@ import { BuildingType, EternumGlobalConfig, RESOURCE_INPUTS, + ID, RESOURCE_INPUTS_SCALED, RESOURCE_OUTPUTS, ResourcesIds, @@ -284,7 +285,7 @@ export const SelectPreviewBuildingMenu = () => { ); }; -export const BuildingCard = ({ +const BuildingCard = ({ buildingId, onClick, active, @@ -362,7 +363,7 @@ export const ResourceInfo = ({ extraButtons = [], }: { resourceId: number; - entityId: bigint | undefined; + entityId: ID | undefined; extraButtons?: React.ReactNode[]; }) => { const cost = RESOURCE_INPUTS_SCALED[resourceId]; @@ -394,7 +395,7 @@ export const ResourceInfo = ({
consumed per/s
{Object.keys(cost).map((resourceId) => { - const balance = getBalance(entityId || 0n, cost[Number(resourceId)].resource); + const balance = getBalance(entityId || 0, cost[Number(resourceId)].resource); return ( {Object.keys(buildingCost).map((resourceId, index) => { - const balance = getBalance(entityId || 0n, buildingCost[Number(resourceId)].resource); + const balance = getBalance(entityId || 0, buildingCost[Number(resourceId)].resource); return ( { @@ -492,7 +493,7 @@ export const BuildingInfo = ({ {resourceProduced !== 0 && ongoingCost && Object.keys(ongoingCost).map((resourceId, index) => { - const balance = getBalance(entityId || 0n, ongoingCost[Number(resourceId)].resource); + const balance = getBalance(entityId || 0, ongoingCost[Number(resourceId)].resource); return ( One time cost
{Object.keys(cost).map((resourceId, index) => { - const balance = getBalance(entityId || 0n, cost[Number(resourceId)].resource); + const balance = getBalance(entityId || 0, cost[Number(resourceId)].resource); return ( { - // only mine = true - return ( -
- {/* // todo: get entities that have inventory instead */} - {/* {[].map((entity) => { - return ; - })} */} -
- ); -}; diff --git a/client/src/ui/components/entities/Entity.tsx b/client/src/ui/components/entities/Entity.tsx index f6b711af0..2a6364788 100644 --- a/client/src/ui/components/entities/Entity.tsx +++ b/client/src/ui/components/entities/Entity.tsx @@ -5,10 +5,10 @@ import { getEntitiesUtils } from "@/hooks/helpers/useEntities"; import { getResourcesUtils, useOwnedEntitiesOnPosition } from "@/hooks/helpers/useResources"; import { getStructureByEntityId } from "@/hooks/helpers/useStructures"; import useBlockchainStore from "@/hooks/store/useBlockchainStore"; -import { formatSecondsLeftInDaysHours } from "@/ui/components/cityview/realm/labor/laborUtils"; +import { formatSecondsLeftInDaysHours } from "@/ui/utils/utils"; import { ResourceCost } from "@/ui/elements/ResourceCost"; import { divideByPrecision } from "@/ui/utils/utils"; -import { EntityState, EntityType, determineEntityState } from "@bibliothecadao/eternum"; +import { EntityState, EntityType, ID, determineEntityState } from "@bibliothecadao/eternum"; import clsx from "clsx"; import React, { useMemo, useState } from "react"; import { DepositResources } from "../resources/DepositResources"; @@ -27,7 +27,7 @@ const entityName: Record = { }; type EntityProps = { - entityId: bigint; + entityId: ID; idleOnly?: boolean; selectedCaravan?: number; } & React.HTMLAttributes; @@ -45,18 +45,13 @@ export const Entity = ({ entityId, ...props }: EntityProps) => { const entity = getEntityInfo(entityId); const entityResources = getResourcesFromBalance(entityId); const hasResources = entityResources.length > 0; - const entityState = determineEntityState( - nextBlockTimestamp, - entity.blocked, - Number(entity.arrivalTime), - hasResources, - ); + const entityState = determineEntityState(nextBlockTimestamp, entity.blocked, entity.arrivalTime, hasResources); const depositEntityId = getOwnedEntityOnPosition(entityId); - const structureAtPosition = getStructureByEntityId(depositEntityId || 0n); + const structureAtPosition = getStructureByEntityId(depositEntityId || 0); const battleInProgress = useMemo(() => { - if (!structureAtPosition || !structureAtPosition.protector || structureAtPosition.protector.battle_id === 0n) { + if (!structureAtPosition || !structureAtPosition.protector || structureAtPosition.protector.battle_id === 0) { return false; } const currentTimestamp = useBlockchainStore.getState().nextBlockTimestamp; diff --git a/client/src/ui/components/entities/EntityPopulation.tsx b/client/src/ui/components/entities/EntityPopulation.tsx deleted file mode 100644 index 076e35ddd..000000000 --- a/client/src/ui/components/entities/EntityPopulation.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { useDojo } from "@/hooks/context/DojoContext"; -import { BASE_POPULATION_CAPACITY } from "@bibliothecadao/eternum"; -import { useComponentValue } from "@dojoengine/react"; -import { getEntityIdFromKeys } from "@dojoengine/utils"; - -export const EntityPopulation = ({ entityId }: { entityId: any }) => { - const { - setup: { - components: { Population }, - }, - } = useDojo(); - - const population = useComponentValue(Population, getEntityIdFromKeys([entityId])); - - return ( -
-
Population: {population?.population}
-
Capacity: {(population?.capacity || 0) + BASE_POPULATION_CAPACITY}
-
- ); -}; diff --git a/client/src/ui/components/entities/SelectLocationPanel.tsx b/client/src/ui/components/entities/SelectLocationPanel.tsx index f3a53e73f..ad53ea1b2 100644 --- a/client/src/ui/components/entities/SelectLocationPanel.tsx +++ b/client/src/ui/components/entities/SelectLocationPanel.tsx @@ -6,7 +6,7 @@ import { SortButton, SortInterface } from "@/ui/elements/SortButton"; import { SortPanel } from "@/ui/elements/SortPanel"; import TextInput from "@/ui/elements/TextInput"; import { getRealm } from "@/ui/utils/realms"; -import { SelectableLocationInterface, getOrderName } from "@bibliothecadao/eternum"; +import { ID, SelectableLocationInterface, getOrderName } from "@bibliothecadao/eternum"; import { Entity, getComponentValue } from "@dojoengine/recs"; import { getEntityIdFromKeys } from "@dojoengine/utils"; import { useDeferredValue, useEffect, useMemo, useState } from "react"; @@ -17,10 +17,10 @@ export const SelectLocationPanel = ({ selectedEntityId, setSelectedEntityId, }: { - travelingEntityId: bigint; + travelingEntityId: ID; entityIds: Entity[]; - selectedEntityId: bigint | undefined; - setSelectedEntityId: (selectedEntityId: bigint) => void; + selectedEntityId: ID | undefined; + setSelectedEntityId: (selectedEntityId: ID) => void; }) => { const [nameFilter, setNameFilter] = useState(""); const [originalLocations, setOriginalLocations] = useState([]); @@ -59,7 +59,7 @@ export const SelectLocationPanel = ({ useEffect(() => { const buildSelectableLocations = () => { - const entityOwner = getComponentValue(EntityOwner, getEntityIdFromKeys([travelingEntityId])); + const entityOwner = getComponentValue(EntityOwner, getEntityIdFromKeys([BigInt(travelingEntityId)])); let locations = Array.from(entityIds) .map((entity) => { const realm = getComponentValue(Realm, entity); @@ -76,7 +76,7 @@ export const SelectLocationPanel = ({ takerRealmId = realmId; } const entityId = realm?.entity_id || bank?.entity_id; - const distance = entityId ? (calculateDistance(travelingEntityId, BigInt(entityId)) ?? 0) : 0; + const distance = entityId ? (calculateDistance(travelingEntityId, entityId) ?? 0) : 0; const addressName = entityId ? getRealmAddressName(entityId) : ""; return { entityId, @@ -181,7 +181,7 @@ export const SelectLocationPanel = ({ /** * sort realms based on active filters */ -export function sortLocations( +function sortLocations( locations: SelectableLocationInterface[], activeSort: SortInterface, ): SelectableLocationInterface[] { diff --git a/client/src/ui/components/entities/TravelEntityPopup.tsx b/client/src/ui/components/entities/TravelEntityPopup.tsx index 5ccd82ad6..7d4158c03 100644 --- a/client/src/ui/components/entities/TravelEntityPopup.tsx +++ b/client/src/ui/components/entities/TravelEntityPopup.tsx @@ -7,9 +7,10 @@ import { Has, getComponentValue, runQuery } from "@dojoengine/recs"; import { getEntityIdFromKeys } from "@dojoengine/utils"; import { Headline } from "@/ui/elements/Headline"; import { SelectLocationPanel } from "./SelectLocationPanel"; +import { ID } from "@bibliothecadao/eternum"; type TravelEntityPopupProps = { - entityId: bigint; + entityId: ID; onClose: () => void; }; @@ -23,7 +24,7 @@ export const TravelEntityPopup = ({ entityId, onClose }: TravelEntityPopupProps) } = useDojo(); const [selectedTab, setSelectedTab] = useState(0); - const [selectedEntityId, setSelectedEntityId] = useState(); + const [selectedEntityId, setSelectedEntityId] = useState(); const [loading, setLoading] = useState(false); const destinationPosition = selectedEntityId diff --git a/client/src/ui/components/hints/HintModal.tsx b/client/src/ui/components/hints/HintModal.tsx index 855b9f0b5..23c54219f 100644 --- a/client/src/ui/components/hints/HintModal.tsx +++ b/client/src/ui/components/hints/HintModal.tsx @@ -112,7 +112,7 @@ export const HintModal = ({ initialActiveSection }: HintModalProps) => { ); }; -export const Banking = () => { +const Banking = () => { return (
Trading diff --git a/client/src/ui/components/hyperstructures/HyperstructurePanel.tsx b/client/src/ui/components/hyperstructures/HyperstructurePanel.tsx index fc2d37127..e296e1ca8 100644 --- a/client/src/ui/components/hyperstructures/HyperstructurePanel.tsx +++ b/client/src/ui/components/hyperstructures/HyperstructurePanel.tsx @@ -218,7 +218,7 @@ const HyperstructureLeaderboard = () => {
{playerPoints.addressName}
-
{displayAddress(playerPoints.address)}
+
{displayAddress(playerPoints.address.toString(16))}
{playerPoints.totalPoints.toFixed(2)}
diff --git a/client/src/ui/components/hyperstructures/HyperstructureResourceChip.tsx b/client/src/ui/components/hyperstructures/HyperstructureResourceChip.tsx index 81b95c140..14951da2c 100644 --- a/client/src/ui/components/hyperstructures/HyperstructureResourceChip.tsx +++ b/client/src/ui/components/hyperstructures/HyperstructureResourceChip.tsx @@ -1,4 +1,4 @@ -import { findResourceById, getIconResourceId } from "@bibliothecadao/eternum"; +import { findResourceById, getIconResourceId, ID } from "@bibliothecadao/eternum"; import { ProgressWithPercentage } from "@/hooks/helpers/useHyperstructures"; import { getResourceBalance } from "@/hooks/helpers/useResources"; @@ -9,7 +9,7 @@ import { useEffect, useState } from "react"; import { ResourceIcon } from "../../elements/ResourceIcon"; type HyperstructureResourceChipProps = { - realmEntityId: bigint; + realmEntityId: ID; resourceId: number; progress: ProgressWithPercentage; contributions: Record; diff --git a/client/src/ui/components/hyperstructures/StructureCard.tsx b/client/src/ui/components/hyperstructures/StructureCard.tsx index 80e669053..a243c036f 100644 --- a/client/src/ui/components/hyperstructures/StructureCard.tsx +++ b/client/src/ui/components/hyperstructures/StructureCard.tsx @@ -6,7 +6,7 @@ import Button from "@/ui/elements/Button"; import { NumberInput } from "@/ui/elements/NumberInput"; import { ResourceIcon } from "@/ui/elements/ResourceIcon"; import { currencyFormat } from "@/ui/utils/utils"; -import { EternumGlobalConfig, Position, ResourcesIds } from "@bibliothecadao/eternum"; +import { EternumGlobalConfig, ID, Position, ResourcesIds } from "@bibliothecadao/eternum"; import { useComponentValue } from "@dojoengine/react"; import { getEntityIdFromKeys } from "@dojoengine/utils"; import { ArrowRight } from "lucide-react"; @@ -54,7 +54,7 @@ type MergeTroopsPanelProps = { giverArmy: ArmyInfo; takerArmy?: ArmyInfo; setShowMergeTroopsPopup: (val: boolean) => void; - structureEntityId?: bigint; + structureEntityId?: ID; }; export const MergeTroopsPanel = ({ @@ -71,7 +71,7 @@ export const MergeTroopsPanel = ({
@@ -81,8 +81,8 @@ export const MergeTroopsPanel = ({ type TroopsProps = { giverArmy: ArmyInfo; takerArmy?: ArmyInfo; - giverArmyEntityId: bigint; - structureEntityId?: bigint; + giverArmyEntityId: ID; + structureEntityId?: ID; }; const troopsToFormat = (troops: { knight_count: bigint; paladin_count: bigint; crossbowman_count: bigint }) => { @@ -110,7 +110,7 @@ const TroopExchange = ({ giverArmy, giverArmyEntityId, structureEntityId, takerA [ResourcesIds.Paladin]: 0n, }); - const protector = useComponentValue(Protector, getEntityIdFromKeys([structureEntityId || 0n])); + const protector = useComponentValue(Protector, getEntityIdFromKeys([BigInt(structureEntityId || 0)])); const createProtector = async () => { setLoading(true); @@ -149,10 +149,10 @@ const TroopExchange = ({ giverArmy, giverArmyEntityId, structureEntityId, takerA setTroopsGiven((prev) => ({ ...prev, [resourceId]: amount })); }; - const giverArmyTroops = useComponentValue(Army, getEntityIdFromKeys([giverArmyEntityId]))!.troops; + const giverArmyTroops = useComponentValue(Army, getEntityIdFromKeys([BigInt(giverArmyEntityId)]))!.troops; const receiverArmyTroops = useComponentValue( Army, - getEntityIdFromKeys([takerArmy?.entity_id || protector?.army_id || 0n]), + getEntityIdFromKeys([BigInt(takerArmy?.entity_id || protector?.army_id || 0)]), )?.troops; return ( diff --git a/client/src/ui/components/list/EntityList.tsx b/client/src/ui/components/list/EntityList.tsx index cb1a94ade..5e2c40f58 100644 --- a/client/src/ui/components/list/EntityList.tsx +++ b/client/src/ui/components/list/EntityList.tsx @@ -1,5 +1,6 @@ import { ReactComponent as ArrowRight } from "@/assets/icons/common/arrow-right.svg"; import Button from "@/ui/elements/Button"; +import { ID } from "@bibliothecadao/eternum"; import clsx from "clsx"; import React, { useEffect, useState } from "react"; @@ -13,7 +14,7 @@ interface EntityListProps { }) => React.ReactElement; list: any[]; previous?: any[]; - current?: bigint; + current?: ID; entityContent?: (props: { id: any }) => React.ReactElement | null; questing?: boolean; className?: string; diff --git a/client/src/ui/components/list/RealmListBoxes.tsx b/client/src/ui/components/list/RealmListBoxes.tsx deleted file mode 100644 index 19ea1cff2..000000000 --- a/client/src/ui/components/list/RealmListBoxes.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import clsx from "clsx"; -import { ComponentPropsWithRef } from "react"; -import useUIStore from "@/hooks/store/useUIStore"; -import { useEntities } from "@/hooks/helpers/useEntities"; -import { useQuery } from "@/hooks/helpers/useQuery"; -import { useRealm } from "@/hooks/helpers/useRealm"; -import { useLocation } from "wouter"; - -type RealmSwitchProps = {} & ComponentPropsWithRef<"div">; - -export const RealmListBoxes = ({ className }: RealmSwitchProps) => { - const { playerRealms } = useEntities(); - const { isLocation } = useQuery(); - const { getRealmIdFromRealmEntityId } = useRealm(); - const setIsLoadingScreenEnabled = useUIStore((state) => state.setIsLoadingScreenEnabled); - const [location, setLocation] = useLocation(); - const moveCameraToRealm = useUIStore((state) => state.moveCameraToRealm); - - const isRealmView = location.includes(`/hex`); - - const gotToRealmView = (realm: any) => { - setIsLoadingScreenEnabled(true); - setLocation(`/hex?col=${realm?.position.x}&row=${realm?.position.y}`); - setTimeout(() => { - if (location.includes(`/hex`)) { - setIsLoadingScreenEnabled(false); - } - }, 300); - }; - - const goToMapView = (realm: any) => { - const realmId = getRealmIdFromRealmEntityId(realm.entity_id); - if (!realmId) return; - moveCameraToRealm(Number(realmId)); - }; - - return ( -
-
- {playerRealms().map((realm) => ( -
{ - !isRealmView ? goToMapView(realm) : gotToRealmView(realm); - }} - > -
- {realm?.name} -
-
- ))} -
-
- ); -}; diff --git a/client/src/ui/components/military/ArmyChip.tsx b/client/src/ui/components/military/ArmyChip.tsx index 5d2afe8f9..af3c2e57a 100644 --- a/client/src/ui/components/military/ArmyChip.tsx +++ b/client/src/ui/components/military/ArmyChip.tsx @@ -45,7 +45,7 @@ export const ArmyChip = ({ - + ) : ( <> diff --git a/client/src/ui/components/military/ArmyList.tsx b/client/src/ui/components/military/ArmyList.tsx index 56a17065e..227a515ee 100644 --- a/client/src/ui/components/military/ArmyList.tsx +++ b/client/src/ui/components/military/ArmyList.tsx @@ -26,7 +26,7 @@ export const EntityArmyList = ({ structure }: { structure: PlayerStructure }) => const existingBuildings = useUIStore((state) => state.existingBuildings); const { entityArmies: structureArmies } = useArmiesByEntityOwner({ - entity_owner_entity_id: structure?.entity_id || 0n, + entity_owner_entity_id: structure?.entity_id || 0, }); const selectedQuest = useQuestStore((state) => state.selectedQuest); @@ -149,7 +149,7 @@ const ArmyItem = ({ const { nextBlockTimestamp: currentTimestamp } = useBlockchainStore(); - const battleManager = useMemo(() => new BattleManager(entity?.battle_id || 0n, dojo), [entity?.battle_id, dojo]); + const battleManager = useMemo(() => new BattleManager(entity?.battle_id || 0, dojo), [entity?.battle_id, dojo]); const updatedArmy = useMemo(() => { if (!currentTimestamp) throw new Error("Current timestamp is undefined"); @@ -161,11 +161,11 @@ const ArmyItem = ({ return ( - + ); }; diff --git a/client/src/ui/components/military/ArmyManagementCard.tsx b/client/src/ui/components/military/ArmyManagementCard.tsx index 91dd5e2f6..a4ccf7ffd 100644 --- a/client/src/ui/components/military/ArmyManagementCard.tsx +++ b/client/src/ui/components/military/ArmyManagementCard.tsx @@ -9,12 +9,11 @@ import useUIStore from "@/hooks/store/useUIStore"; import Button from "@/ui/elements/Button"; import { NumberInput } from "@/ui/elements/NumberInput"; import TextInput from "@/ui/elements/TextInput"; -import { currencyFormat, getEntityIdFromKeys } from "@/ui/utils/utils"; -import { Position, ResourcesIds, U32_MAX } from "@bibliothecadao/eternum"; +import { currencyFormat, formatSecondsInHoursMinutes, getEntityIdFromKeys } from "@/ui/utils/utils"; +import { ID, Position, ResourcesIds, U32_MAX } from "@bibliothecadao/eternum"; import { useComponentValue } from "@dojoengine/react"; import { useEffect, useMemo, useState } from "react"; import { useLocation } from "wouter"; -import { formatSecondsInHoursMinutes } from "../cityview/realm/labor/laborUtils"; import { ArmyInfo } from "@/hooks/helpers/useArmies"; import { useStructuresFromPosition } from "@/hooks/helpers/useStructures"; @@ -23,7 +22,7 @@ import { EternumGlobalConfig, resources } from "@bibliothecadao/eternum"; import { LucideArrowRight } from "lucide-react"; type ArmyManagementCardProps = { - owner_entity: bigint; + owner_entity: ID; army: ArmyInfo | undefined; setSelectedEntity?: (entity: ArmyInfo | null) => void; }; @@ -184,7 +183,7 @@ export const ArmyManagementCard = ({ owner_entity, army, setSelectedEntity }: Ar <> Traveling for{" "} {isPassiveTravel - ? formatSecondsInHoursMinutes(army?.arrivalTime!.arrives_at - nextBlockTimestamp || 0) + ? formatSecondsInHoursMinutes(Number(army?.arrivalTime!.arrives_at || 0) - nextBlockTimestamp) : "Arrives Next Tick"} ) : ( @@ -396,7 +395,7 @@ interface TravelToLocationProps { onClose: () => void; } -export const TravelToLocation = ({ +const TravelToLocation = ({ isTraveling, checkSamePosition, entityOwnerPosition, diff --git a/client/src/ui/components/military/ArmyViewCard.tsx b/client/src/ui/components/military/ArmyViewCard.tsx deleted file mode 100644 index 02a8e7dd1..000000000 --- a/client/src/ui/components/military/ArmyViewCard.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import { ArmyInfo } from "@/hooks/helpers/useArmies"; -import { Headline } from "@/ui/elements/Headline"; -import { OrderIcon } from "@/ui/elements/OrderIcon"; -import { getRealmNameById } from "@/ui/utils/realms"; -import { currencyFormat } from "@/ui/utils/utils"; -import { orderNameDict } from "@bibliothecadao/eternum"; -import { InventoryResources } from "../resources/InventoryResources"; - -export const ArmyViewCard = ({ - army, - onClick, - active, - actions, -}: { - army: ArmyInfo; - onClick?: (entityId: string) => void; - active?: boolean; - actions?: boolean; -}) => { - const handleToggle = (id: string) => { - if (onClick) { - if (active) { - return onClick(""); - } - onClick(id); - } - }; - - return ( -
(onClick ? handleToggle(army.entity_id.toString()) : null)} - className={`group hover:bg-gold/10 border relative ${active ? "bg-gold text-brown animate-pulse" : ""}`} - > -
-
- {army.realm && army.realm.order && ( - - )} - {getRealmNameById(BigInt(army.realm?.realm_id || 0n))} -
-
- - {actions && ( -
-
open actions
-
- )} - -
- {" "} - -
{army.name}
-
-
- HP: - {Number(army.health.current.toString()) / 1000} -
-
-
-
-
{currencyFormat(army.troops.crossbowman_count, 0)}
-
-
Crossbowman
-
-
-
-
{currencyFormat(army.troops.knight_count, 0)}
-
-
Knights
-
-
-
-
{currencyFormat(army.troops.paladin_count, 0)}
-
-
Paladins
-
-
- -
-
- ); -}; diff --git a/client/src/ui/components/military/BattlesArmyTable.tsx b/client/src/ui/components/military/BattlesArmyTable.tsx deleted file mode 100644 index f693d1e84..000000000 --- a/client/src/ui/components/military/BattlesArmyTable.tsx +++ /dev/null @@ -1,127 +0,0 @@ -import { ClientComponents } from "@/dojo/createClientComponents"; -import { - BattleInfo, - ExtraBattleInfo, - getBattleInfoByOwnArmyEntityId, - useBattleManager, - usePlayerBattles, -} from "@/hooks/helpers/battles/useBattles"; -import useBlockchainStore from "@/hooks/store/useBlockchainStore"; -import { ResourceIcon } from "@/ui/elements/ResourceIcon"; -import { currencyFormat } from "@/ui/utils/utils"; -import { findResourceById } from "@bibliothecadao/eternum"; -import { useMemo } from "react"; -import { InventoryResources } from "../resources/InventoryResources"; - -export const BattlesArmyTable = () => { - const { playerBattles } = usePlayerBattles(); - const battles = playerBattles(); - - return ( -
-
- {battles.map(({ battle, ownArmy }: any) => { - return ; - })} -
-
- ); -}; - -type BattleChipProps = { - battle: BattleInfo; - ownArmy: ClientComponents["Army"]["schema"]; -}; - -const BattleChip = ({ battle, ownArmy }: BattleChipProps) => { - const currentDefaultTick = useBlockchainStore((state) => state.currentDefaultTick); - - const updatedBattle = useBattleManager(BigInt(battle.entity_id)); - - const extraInfo = useMemo(() => { - const extraInfo = getBattleInfoByOwnArmyEntityId(BigInt(ownArmy.entity_id)); - return extraInfo; - }, [ownArmy]); - - const currentBattle = useMemo(() => { - return updatedBattle.getUpdatedBattle(currentDefaultTick); - }, [currentDefaultTick]); - - const extendedBattle = useMemo(() => { - if (!extraInfo) return; - return formatBattle(currentBattle, extraInfo, ownArmy); - }, [currentDefaultTick]); - - return ( - extendedBattle && ( -
-
-
- - VS. - -
-
- ) - ); -}; - -const ArmyCard = ({ army, position, armyName }: any) => { - return ( -
-
{armyName}
-
- ❤️ - {Number((army.current || 0).toString()) / 1000} -
- - -
- ); -}; - -const TroopsCard = ({ army }: any) => { - const { - troops: { crossbowman_count, paladin_count, knight_count }, - } = army; - const troopCounts = { 250: crossbowman_count, 251: paladin_count, 252: knight_count }; - return ( -
- {Object.entries(troopCounts).map(([troopId, count]) => ( -
- -
{currencyFormat(count, 0)}
-
- ))} -
- ); -}; - -const formatBattle = (currentBattle: any, extraInfo: ExtraBattleInfo, ownArmy: ClientComponents["Army"]["schema"]) => { - if (currentBattle.attack_army.battle_side === extraInfo.opponentArmy.battle_side) { - currentBattle.opponentArmy = { ...currentBattle.attack_army_health, ...extraInfo.opponentArmy }; - - currentBattle.ownArmy = { ...currentBattle.defence_army_health, ...ownArmy }; - } else { - currentBattle.opponentArmy = { ...currentBattle.defence_army_health, ...extraInfo.opponentArmy }; - currentBattle.ownArmy = { ...currentBattle.attack_army_health, ...ownArmy }; - } - - return { - ...currentBattle, - x: extraInfo.x, - y: extraInfo.y, - opponentArmyEntityName: extraInfo.opponentArmyEntityName, - ownArmyEntityName: extraInfo.ownArmyEntityName, - }; -}; diff --git a/client/src/ui/components/military/EntitiesArmyTable.tsx b/client/src/ui/components/military/EntitiesArmyTable.tsx index fe3fd11b7..9cae057f1 100644 --- a/client/src/ui/components/military/EntitiesArmyTable.tsx +++ b/client/src/ui/components/military/EntitiesArmyTable.tsx @@ -1,13 +1,25 @@ import { ArmyInfo, useArmiesByEntityOwner } from "@/hooks/helpers/useArmies"; import { useEntities } from "@/hooks/helpers/useEntities"; import { Headline } from "@/ui/elements/Headline"; +import { ID } from "@bibliothecadao/eternum"; import { ArmyChip } from "./ArmyChip"; -type EntityArmyTableProps = { - structureEntityId: bigint | undefined; +export const EntitiesArmyTable = () => { + const { playerStructures } = useEntities(); + + return playerStructures().map((entity: any) => { + return ( +
+ {entity.name} +
+ +
+
+ ); + }); }; -export const EntityArmyTable = ({ structureEntityId }: EntityArmyTableProps) => { +const EntityArmyTable = ({ structureEntityId }: { structureEntityId: ID | undefined }) => { if (!structureEntityId) { return
Entity not found
; } @@ -25,18 +37,3 @@ export const EntityArmyTable = ({ structureEntityId }: EntityArmyTableProps) => return
{armyElements()}
; }; - -export const EntitiesArmyTable = () => { - const { playerStructures } = useEntities(); - - return playerStructures().map((entity: any) => { - return ( -
- {entity.name} -
- -
-
- ); - }); -}; diff --git a/client/src/ui/components/military/PillageHistory.tsx b/client/src/ui/components/military/PillageHistory.tsx index d76c2c7e2..c8fbb3138 100644 --- a/client/src/ui/components/military/PillageHistory.tsx +++ b/client/src/ui/components/military/PillageHistory.tsx @@ -4,7 +4,7 @@ import { BUILDING_IMAGES_PATH } from "@/ui/config"; import { Headline } from "@/ui/elements/Headline"; import { ResourceCost } from "@/ui/elements/ResourceCost"; import { divideByPrecision } from "@/ui/utils/utils"; -import { BattleSide, BuildingType, Resource } from "@bibliothecadao/eternum"; +import { BattleSide, BuildingType, ID, Resource } from "@bibliothecadao/eternum"; import { useEffect, useRef, useState } from "react"; import { Subscription } from "rxjs"; @@ -12,8 +12,8 @@ export const PillageHistory = ({ structureId, attackerRealmEntityId, }: { - structureId: bigint; - attackerRealmEntityId: bigint; + structureId: ID; + attackerRealmEntityId: ID; }) => { const { setup: { @@ -114,9 +114,9 @@ export const PillageHistory = ({ }; const formatPillageEvent = (event: Event) => { - const structureId = BigInt(event.keys[1]); - const attackerRealmEntityId = BigInt(event.keys[2]); - const armyId = BigInt(event.keys[3]); + const structureId = Number(event.keys[1]); + const attackerRealmEntityId = Number(event.keys[2]); + const armyId = Number(event.keys[3]); const owner = BigInt(event.keys[4]); const winner = Number(event.data[0]); diff --git a/client/src/ui/components/military/TroopSelect.tsx b/client/src/ui/components/military/TroopSelect.tsx deleted file mode 100644 index 88f67ff4a..000000000 --- a/client/src/ui/components/military/TroopSelect.tsx +++ /dev/null @@ -1,138 +0,0 @@ -import { useDojo } from "@/hooks/context/DojoContext"; -import { getResourceBalance } from "@/hooks/helpers/useResources"; -import Button from "@/ui/elements/Button"; -import TextInput from "@/ui/elements/TextInput"; -import { currencyFormat } from "@/ui/utils/utils"; -import { ResourcesIds } from "@bibliothecadao/eternum"; -import { useEffect, useState } from "react"; - -const troops = [ - { name: ResourcesIds.Knight, cost: 10, attack: 10, defense: 10, strong: "Cavalry", weak: "Archers" }, - { name: ResourcesIds.Crossbowman, cost: 10, attack: 10, defense: 10, strong: "Swordsmen", weak: "Cavalry" }, - { name: ResourcesIds.Paladin, cost: 10, attack: 10, defense: 10, strong: "Archers", weak: "Swordsmen" }, -]; - -export const TroopSelect = ({ entity }: any) => { - const { - account: { account }, - setup: { - systemCalls: { create_army }, - }, - } = useDojo(); - - const [isLoading, setIsLoading] = useState(false); - const [canCreate, setCanCreate] = useState(false); - const [troopCounts, setTroopCounts] = useState<{ [key: number]: number }>({ - [ResourcesIds.Knight]: 1, - [ResourcesIds.Crossbowman]: 1, - [ResourcesIds.Paladin]: 1, - }); - - const handleTroopCountChange = (troopName: number, count: number) => { - setTroopCounts((prev) => ({ ...prev, [troopName]: count })); - }; - - const calculateTotalCost = () => { - return troops.reduce((total, troop) => { - return total + troop.cost * troopCounts[troop.name]; - }, 0); - }; - - const handleCreateArmy = () => { - setIsLoading(true); - create_army({ - signer: account, - army_owner_id: entity.entity_id, - is_defensive_army: false, - }).finally(() => setIsLoading(false)); - }; - - const { getBalance } = getResourceBalance(); - - useEffect(() => { - let canCreate = true; - Object.keys(troopCounts).forEach((troopId) => { - const count = troopCounts[Number(troopId)]; - const balance = getBalance(entity.entity_id, Number(troopId)).balance; - if (count > balance) { - canCreate = false; - } - }); - setCanCreate(canCreate); - }, [troopCounts]); - - return ( -
-

New Army

- -
- {troops.map((troop) => ( -
-
{ResourcesIds[troop.name]}
-
- Available:{" "} - {currencyFormat( - getBalance(entity.entity_id, troop.name).balance - ? Number(getBalance(entity.entity_id, troop.name).balance) - : 0, - 2, - )}{" "} - {} -
-
Str vs {troop.strong}
-
Wk vs {troop.weak}
-
-
Atk: {troop.attack}
-
Def: {troop.defense}
-
- -
-
amount:
- handleTroopCountChange(troop.name, parseInt(amount))} - /> -
-
- ))} -
- -
-

Enlisting

-
- {ResourcesIds[ResourcesIds.Knight]}: {troopCounts[ResourcesIds.Knight]} -
-
- {ResourcesIds[ResourcesIds.Crossbowman]}: {troopCounts[ResourcesIds.Crossbowman]} -
-
- {ResourcesIds[ResourcesIds.Paladin]}: {troopCounts[ResourcesIds.Paladin]} -
-
-
- -
- ); -}; - -export const StepOne = () => { - return ( -
-
- -
-
- -
-
- ); -}; diff --git a/client/src/ui/components/models/buildings/worldmap/Castles.tsx b/client/src/ui/components/models/buildings/worldmap/Castles.tsx deleted file mode 100644 index 24472adf7..000000000 --- a/client/src/ui/components/models/buildings/worldmap/Castles.tsx +++ /dev/null @@ -1,113 +0,0 @@ -import { biomes } from "@bibliothecadao/eternum"; -import { useGLTF } from "@react-three/drei"; -import { useMemo } from "react"; -import realmHexPositions from "../../../../../data/geodata/hex/realmHexPositions.json"; -import { useGetRealms } from "../../../../../hooks/helpers/useRealm"; -import useRealmStore from "../../../../../hooks/store/useRealmStore"; -import { Hexagon } from "../../../../../types"; -import { HexPositions, getRealmUIPosition, pseudoRandom } from "../../../../utils/utils"; - -type Castle = { - uiPos: { x: number; y: number }; - contractPos: { x: number; y: number }; - index: number; - depth: number; - id: bigint; -}; - -type CastlesProps = { - hexData: Hexagon[]; -}; - -const BIOMES = biomes as Record; - -export const OtherCastles = ({ hexData }: CastlesProps) => { - const realms = useGetRealms(); - const model = useGLTF("/models/buildings/castle.glb"); - - const realmEntityIds = useRealmStore((state) => state.realmEntityIds); - - const realmPositions = realmHexPositions as HexPositions; - - let castles = useMemo(() => { - return realms - .filter((realm) => !realmEntityIds.map((r) => r.realmEntityId).includes(realm.entity_id)) - .map((realm) => { - const colrow = realmPositions[Number(realm.realmId).toString()][0]; - const hexIndex = hexData.findIndex((h) => h.col === colrow.col && h.row === colrow.row); - // to have the exact height of the hexagon and place castle on top - return { - uiPos: getRealmUIPosition(realm.realmId), - contractPos: { x: colrow.col, y: colrow.row }, - index: hexIndex, - depth: BIOMES[hexData[hexIndex].biome].depth, - id: realm.entity_id, - }; - }) - .filter(Boolean) as Castle[]; - }, []); - - return ( - - {castles.map((castle) => { - const { uiPos: position, index } = castle; - if (index === -1) return null; - return ( - - - - ); - })} - - ); -}; - -export const MyCastles = ({ hexData }: CastlesProps) => { - const realmEntityIds = useRealmStore((state) => state.realmEntityIds); - - const model = useGLTF("/models/buildings/castle.glb"); - - const realmPositions = realmHexPositions as HexPositions; - - let castles = useMemo(() => { - return realmEntityIds - .map((entity) => { - const colrow = realmPositions[Number(entity.realmId).toString()][0]; - const hexIndex = hexData.findIndex((h) => h.col === colrow.col && h.row === colrow.row); - // to have the exact height of the hexagon and place castle on top - return { - position: getRealmUIPosition(entity.realmId), - index: hexIndex, - depth: BIOMES[hexData[hexIndex].biome].depth, - }; - }) - .filter(Boolean); - }, []); - - return ( - - {castles.map((castle) => { - const { position, index, depth } = castle; - - if (index === -1) return null; - return ( - - ); - })} - - ); -}; diff --git a/client/src/ui/components/models/buildings/worldmap/InstancedLabels.tsx b/client/src/ui/components/models/buildings/worldmap/InstancedLabels.tsx deleted file mode 100644 index e69de29bb..000000000 diff --git a/client/src/ui/components/models/buildings/worldmap/Structures.tsx b/client/src/ui/components/models/buildings/worldmap/Structures.tsx index 00c20d0b7..a377a64e6 100644 --- a/client/src/ui/components/models/buildings/worldmap/Structures.tsx +++ b/client/src/ui/components/models/buildings/worldmap/Structures.tsx @@ -2,7 +2,7 @@ import { HyperstructureEventInterface } from "@/dojo/events/hyperstructureEventQ import useLeaderBoardStore from "@/hooks/store/useLeaderBoardStore"; import useUIStore from "@/hooks/store/useUIStore"; import { getUIPositionFromColRow } from "@/ui/utils/utils"; -import { StructureType } from "@bibliothecadao/eternum"; +import { ID, StructureType } from "@bibliothecadao/eternum"; import { Billboard, Image, useGLTF, useTexture } from "@react-three/drei"; import { useEffect, useMemo, useState } from "react"; import * as THREE from "three"; @@ -10,7 +10,7 @@ import { InstancedBanks } from "./InstancedBanks"; import { InstancedCastles } from "./InstancedCastles"; import { ShardsMines } from "./ShardsMines"; -export type Structure = { col: number; row: number; type: StructureType; entityId: bigint }; +type Structure = { col: number; row: number; type: StructureType; entityId: ID }; export const Structures = () => { const existingStructures = useUIStore((state) => state.existingStructures); @@ -52,7 +52,7 @@ const BuiltStructure = ({ structureCategory, rotation, }: { - structure: { col: number; row: number; type: StructureType; entityId: bigint }; + structure: { col: number; row: number; type: StructureType; entityId: ID }; models: any; structureCategory: number; rotation?: THREE.Euler; diff --git a/client/src/ui/components/navigation/Config.tsx b/client/src/ui/components/navigation/Config.tsx index cbe7f73a5..3b082df2f 100644 --- a/client/src/ui/components/navigation/Config.tsx +++ b/client/src/ui/components/navigation/Config.tsx @@ -1,17 +1,11 @@ -export type OSWindows = - | "Event Log" +type OSWindows = | "Leaderboard" | "World Structures" - | "Structures" | "Settings" - | "Resources" | "Military" - | "Entity Details" | "Trade" | "Construction" | "Assistant" - | "Create Offer" - | "Accept Offer" | "Quests" | "Guilds"; @@ -24,18 +18,12 @@ export interface OSInterface { hintSection?: string; } -export const eventLog: OSWindows = "Event Log"; export const leaderboard: OSWindows = "Leaderboard"; export const worldStructures: OSWindows = "World Structures"; -export const structures: OSWindows = "Structures"; export const settings: OSWindows = "Settings"; -export const resources: OSWindows = "Resources"; export const military: OSWindows = "Military"; -export const entityDetails: OSWindows = "Entity Details"; export const trade: OSWindows = "Trade"; export const construction: OSWindows = "Construction"; export const assistant: OSWindows = "Assistant"; -export const createOffer: OSWindows = "Create Offer"; -export const acceptOfferTitle: OSWindows = "Accept Offer"; export const quests: OSWindows = "Quests"; export const guilds: OSWindows = "Guilds"; diff --git a/client/src/ui/components/navigation/SideBar.tsx b/client/src/ui/components/navigation/SideBar.tsx deleted file mode 100644 index bd42b1c68..000000000 --- a/client/src/ui/components/navigation/SideBar.tsx +++ /dev/null @@ -1,7 +0,0 @@ -interface SideBarProps { - children: React.ReactNode; -} - -export const SideBar = ({ children }: SideBarProps) => { - return
{children}
; -}; diff --git a/client/src/ui/components/quest/QuestInfo.tsx b/client/src/ui/components/quest/QuestInfo.tsx index bc6e2ca14..4cc87d251 100644 --- a/client/src/ui/components/quest/QuestInfo.tsx +++ b/client/src/ui/components/quest/QuestInfo.tsx @@ -7,8 +7,9 @@ import { Check, ShieldQuestion } from "lucide-react"; import { multiplyByPrecision } from "@/ui/utils/utils"; import { ResourceCost } from "@/ui/elements/ResourceCost"; import { Prize, Quest, QuestStatus } from "@/hooks/helpers/useQuests"; +import { ID } from "@bibliothecadao/eternum"; -export const QuestInfo = ({ quest, entityId }: { quest: Quest; entityId: bigint }) => { +export const QuestInfo = ({ quest, entityId }: { quest: Quest; entityId: ID }) => { const { setup: { systemCalls: { mint_resources_and_claim_quest }, diff --git a/client/src/ui/components/quest/QuestList.tsx b/client/src/ui/components/quest/QuestList.tsx index bdf08bf9b..df37b1ecc 100644 --- a/client/src/ui/components/quest/QuestList.tsx +++ b/client/src/ui/components/quest/QuestList.tsx @@ -6,8 +6,9 @@ import { useDojo } from "@/hooks/context/DojoContext"; import { useRealm } from "@/hooks/helpers/useRealm"; import { multiplyByPrecision } from "@/ui/utils/utils"; import { Prize, Quest, QuestStatus, useQuests } from "@/hooks/helpers/useQuests"; +import { ID } from "@bibliothecadao/eternum"; -export const QuestList = ({ quests, entityId }: { quests: Quest[]; entityId: bigint | undefined }) => { +export const QuestList = ({ quests, entityId }: { quests: Quest[]; entityId: ID | undefined }) => { const [showCompletedQuests, setShowCompletedQuests] = useState(false); const [skipTutorial, setSkipTutorial] = useState(false); const [maxDepthToShow, setMaxDepthToShow] = useState(0); @@ -82,7 +83,7 @@ const QuestCard = ({ quest }: { quest: Quest }) => { ); }; -const SkipTutorial = ({ entityId }: { entityId: bigint }) => { +const SkipTutorial = ({ entityId }: { entityId: ID }) => { const { setup: { systemCalls: { mint_resources_and_claim_quest }, diff --git a/client/src/ui/components/quest/QuestPanel.tsx b/client/src/ui/components/quest/QuestPanel.tsx index c53442b54..1537789a2 100644 --- a/client/src/ui/components/quest/QuestPanel.tsx +++ b/client/src/ui/components/quest/QuestPanel.tsx @@ -1,10 +1,10 @@ +import { useQuests } from "@/hooks/helpers/useQuests"; import { useQuestStore } from "@/hooks/store/useQuestStore"; +import { ID } from "@bibliothecadao/eternum"; import { QuestInfo } from "./QuestInfo"; import { QuestList } from "./QuestList"; -import { useQuests } from "@/hooks/helpers/useQuests"; -import { useMemo } from "react"; -export const QuestPanel = ({ entityId }: { entityId: bigint | undefined }) => { +export const QuestPanel = ({ entityId }: { entityId: ID | undefined }) => { const { selectedQuest } = useQuestStore((state) => ({ selectedQuest: state.selectedQuest, })); @@ -14,7 +14,7 @@ export const QuestPanel = ({ entityId }: { entityId: bigint | undefined }) => { return selectedQuest ? (
- +
) : ( diff --git a/client/src/ui/components/resources/DepositResources.tsx b/client/src/ui/components/resources/DepositResources.tsx index d4e96441b..0d2230390 100644 --- a/client/src/ui/components/resources/DepositResources.tsx +++ b/client/src/ui/components/resources/DepositResources.tsx @@ -3,12 +3,12 @@ import { getResourcesUtils, useOwnedEntitiesOnPosition } from "@/hooks/helpers/u import useBlockchainStore from "@/hooks/store/useBlockchainStore"; import Button from "@/ui/elements/Button"; import { getEntityIdFromKeys } from "@/ui/utils/utils"; -import { EntityState, determineEntityState } from "@bibliothecadao/eternum"; +import { EntityState, ID, determineEntityState } from "@bibliothecadao/eternum"; import { getComponentValue } from "@dojoengine/recs"; import { useState } from "react"; type DepositResourcesProps = { - entityId: bigint; + entityId: ID; battleInProgress?: boolean; armyInBattle: boolean; }; @@ -24,7 +24,7 @@ export const DepositResources = ({ entityId, battleInProgress, armyInBattle }: D const nextBlockTimestamp = useBlockchainStore.getState().nextBlockTimestamp; const { getOwnedEntityOnPosition } = useOwnedEntitiesOnPosition(); - const arrivalTime = getComponentValue(setup.components.ArrivalTime, getEntityIdFromKeys([entityId])); + const arrivalTime = getComponentValue(setup.components.ArrivalTime, getEntityIdFromKeys([BigInt(entityId)])); const depositEntityId = getOwnedEntityOnPosition(entityId); @@ -35,7 +35,7 @@ export const DepositResources = ({ entityId, battleInProgress, armyInBattle }: D inventoryResources.length > 0, ); - const onOffload = async (receiverEntityId: bigint) => { + const onOffload = async (receiverEntityId: ID) => { setIsLoading(true); if (entityId && inventoryResources.length > 0) { await setup.systemCalls diff --git a/client/src/ui/components/resources/EntityResourceTable.tsx b/client/src/ui/components/resources/EntityResourceTable.tsx index 381a78b8e..b6f09e32d 100644 --- a/client/src/ui/components/resources/EntityResourceTable.tsx +++ b/client/src/ui/components/resources/EntityResourceTable.tsx @@ -1,7 +1,7 @@ -import { RESOURCE_TIERS } from "@bibliothecadao/eternum"; +import { ID, RESOURCE_TIERS } from "@bibliothecadao/eternum"; import { ResourceChip } from "./ResourceChip"; -export const EntityResourceTable = ({ entityId }: { entityId: bigint | undefined }) => { +export const EntityResourceTable = ({ entityId }: { entityId: ID | undefined }) => { if (!entityId) { return
Entity not found
; } diff --git a/client/src/ui/components/resources/InventoryResources.tsx b/client/src/ui/components/resources/InventoryResources.tsx index 1ed229ed2..4b2d1372a 100644 --- a/client/src/ui/components/resources/InventoryResources.tsx +++ b/client/src/ui/components/resources/InventoryResources.tsx @@ -1,7 +1,7 @@ import { getResourceBalance, getResourcesUtils } from "@/hooks/helpers/useResources"; import { ResourceCost } from "@/ui/elements/ResourceCost"; import { divideByPrecision } from "@/ui/utils/utils"; -import { ResourcesIds } from "@bibliothecadao/eternum"; +import { ID, ResourcesIds } from "@bibliothecadao/eternum"; import { useMemo, useState } from "react"; export const InventoryResources = ({ @@ -12,7 +12,7 @@ export const InventoryResources = ({ resourcesIconSize = "sm", textSize, }: { - entityIds: bigint[]; + entityIds: ID[]; max?: number; className?: string; dynamic?: ResourcesIds[]; diff --git a/client/src/ui/components/resources/ResourceChip.tsx b/client/src/ui/components/resources/ResourceChip.tsx index ccc25fb2f..0320169bf 100644 --- a/client/src/ui/components/resources/ResourceChip.tsx +++ b/client/src/ui/components/resources/ResourceChip.tsx @@ -1,4 +1,4 @@ -import { findResourceById, getIconResourceId } from "@bibliothecadao/eternum"; +import { findResourceById, getIconResourceId, ID } from "@bibliothecadao/eternum"; import { useProductionManager } from "@/hooks/helpers/useResources"; import useBlockchainStore from "@/hooks/store/useBlockchainStore"; @@ -13,8 +13,8 @@ export const ResourceChip = ({ entityId, }: { isLabor?: boolean; - resourceId: number; - entityId: bigint; + resourceId: ID; + entityId: ID; }) => { const currentDefaultTick = useBlockchainStore((state) => state.currentDefaultTick); const productionManager = useProductionManager(entityId, resourceId); diff --git a/client/src/ui/components/resources/ResourceWeight.tsx b/client/src/ui/components/resources/ResourceWeight.tsx index 3adb6ab0d..012fef2a3 100644 --- a/client/src/ui/components/resources/ResourceWeight.tsx +++ b/client/src/ui/components/resources/ResourceWeight.tsx @@ -1,8 +1,8 @@ import { getResourceBalance } from "@/hooks/helpers/useResources"; import { divideByPrecision, multiplyByPrecision } from "@/ui/utils/utils"; -import { EternumGlobalConfig, Resource, ResourcesIds, WEIGHTS } from "@bibliothecadao/eternum"; +import { EternumGlobalConfig, ID, Resource, ResourcesIds, WEIGHTS } from "@bibliothecadao/eternum"; import { useEffect, useState } from "react"; -import { getTotalResourceWeight } from "../cityview/realm/trade/utils"; +import { getTotalResourceWeight } from "@/ui/utils/utils"; export const TravelInfo = ({ entityId, @@ -11,7 +11,7 @@ export const TravelInfo = ({ setCanCarry, isAmm, }: { - entityId: bigint; + entityId: ID; resources: Resource[]; travelTime?: number; setCanCarry?: (canContinue: boolean) => void; diff --git a/client/src/ui/components/structures/RealmViewCard.tsx b/client/src/ui/components/structures/RealmViewCard.tsx deleted file mode 100644 index b0ab04a9d..000000000 --- a/client/src/ui/components/structures/RealmViewCard.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { ClientComponents } from "@/dojo/createClientComponents"; -import Button from "@/ui/elements/Button"; -import { getRealm } from "@/ui/utils/realms"; - -export const RealmViewCard = ({ - realm, - onPillage, - onSiege, - self, -}: { - realm: ClientComponents["Realm"]["schema"]; - onPillage: () => void; - onSiege: () => void; - self: boolean; -}) => { - const realmData = getRealm(BigInt(realm.realm_id)); - return ( -
-

- {realmData?.name} -{realm.realm_id.toString()} -

- - {!self && ( -
- - -
- )} -
- ); -}; diff --git a/client/src/ui/components/structures/construction/StructureConstructionMenu.tsx b/client/src/ui/components/structures/construction/StructureConstructionMenu.tsx index 895266ee3..e3e0edeaf 100644 --- a/client/src/ui/components/structures/construction/StructureConstructionMenu.tsx +++ b/client/src/ui/components/structures/construction/StructureConstructionMenu.tsx @@ -5,6 +5,7 @@ import { BuildingType, EternumGlobalConfig, HYPERSTRUCTURE_POINTS_PER_CYCLE, + ID, RESOURCE_INFORMATION, RESOURCE_INPUTS_SCALED, STRUCTURE_COSTS_SCALED, @@ -92,77 +93,13 @@ export const StructureConstructionMenu = () => { ); }; -export const ResourceInfo = ({ resourceId, entityId }: { resourceId: number; entityId: bigint | undefined }) => { - const cost = RESOURCE_INPUTS_SCALED[resourceId]; - - const buildingCost = BUILDING_COSTS_SCALED[BuildingType.Resource]; - - const population = BUILDING_POPULATION[BuildingType.Resource]; - - const capacity = BUILDING_CAPACITY[BuildingType.Resource]; - - const information = RESOURCE_INFORMATION[resourceId]; - - const { getBalance } = getResourceBalance(); - - return ( -
- Building - - {population !== 0 &&
Increases Population: +{population}
} - - {capacity !== 0 &&
Increases Capacity: +{capacity}
} - - {findResourceById(resourceId)?.trait && ( -
-
Produces: +10
- - {findResourceById(resourceId)?.trait || ""} every cycle -
- )} - -
consumed per/s
-
- {Object.keys(cost).map((resourceId) => { - const balance = getBalance(entityId || 0n, cost[Number(resourceId)].resource); - - return ( - - ); - })} -
- -
One Time Cost
- -
- {Object.keys(buildingCost).map((resourceId, index) => { - const balance = getBalance(entityId || 0n, buildingCost[Number(resourceId)].resource); - return ( - - ); - })} -
-
- ); -}; - -export const StructureInfo = ({ +const StructureInfo = ({ structureId, entityId, extraButtons = [], }: { structureId: number; - entityId: bigint | undefined; + entityId: ID | undefined; extraButtons?: React.ReactNode[]; }) => { const cost = STRUCTURE_COSTS_SCALED[structureId]; @@ -185,7 +122,7 @@ export const StructureInfo = ({
One time cost
{Object.keys(cost).map((resourceId, index) => { - const balance = getBalance(entityId || 0n, cost[Number(resourceId)].resource); + const balance = getBalance(entityId || 0, cost[Number(resourceId)].resource); return ( { const { setup: { @@ -101,7 +97,7 @@ export const StructurePreview = () => { ) : null; }; -export const canPlaceStructure = ( +const canPlaceStructure = ( col: number, row: number, structures: any[], diff --git a/client/src/ui/components/trading/MarketModal.tsx b/client/src/ui/components/trading/MarketModal.tsx index bd24a8b03..4a228dfe1 100644 --- a/client/src/ui/components/trading/MarketModal.tsx +++ b/client/src/ui/components/trading/MarketModal.tsx @@ -8,7 +8,7 @@ import CircleButton from "@/ui/elements/CircleButton"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/ui/elements/Select"; import { Tabs } from "@/ui/elements/tab"; import { BuildingThumbs } from "@/ui/modules/navigation/LeftNavigationModule"; -import { MarketInterface, ResourcesIds, resources } from "@bibliothecadao/eternum"; +import { ID, MarketInterface, ResourcesIds, resources } from "@bibliothecadao/eternum"; import { useMemo, useState } from "react"; import { BankPanel } from "../bank/BankList"; import { HintModal } from "../hints/HintModal"; @@ -89,7 +89,7 @@ export const MarketModal = () => {
- setRealmEntityId(ID(trait))}> @@ -154,7 +154,7 @@ export const MarketModal = () => { ); }; -export const MarketResourceSidebar = ({ +const MarketResourceSidebar = ({ entityId, search, onClick, @@ -162,7 +162,7 @@ export const MarketResourceSidebar = ({ resourceAskOffers, resourceBidOffers, }: { - entityId: bigint; + entityId: ID; search: string; onClick: (value: number) => void; selectedResource: number; @@ -205,7 +205,7 @@ export const MarketResourceSidebar = ({ return ( { +const TransferView = () => { const { playerRealms, playerStructures, otherRealms } = useEntities(); return ( diff --git a/client/src/ui/components/trading/MarketOrderPanel.tsx b/client/src/ui/components/trading/MarketOrderPanel.tsx index ac9f91bd2..b7f40d6c6 100644 --- a/client/src/ui/components/trading/MarketOrderPanel.tsx +++ b/client/src/ui/components/trading/MarketOrderPanel.tsx @@ -8,6 +8,7 @@ import TextInput from "@/ui/elements/TextInput"; import { currencyFormat, divideByPrecision, multiplyByPrecision } from "@/ui/utils/utils"; import { EternumGlobalConfig, + ID, MarketInterface, ONE_MONTH, Resources, @@ -15,7 +16,7 @@ import { findResourceById, } from "@bibliothecadao/eternum"; import { useMemo, useState } from "react"; -import { getTotalResourceWeight } from "../cityview/realm/trade/utils"; +import { getTotalResourceWeight } from "@/ui/utils/utils"; import { useProductionManager } from "@/hooks/helpers/useResources"; import { useRealm } from "@/hooks/helpers/useRealm"; @@ -28,7 +29,7 @@ export const MarketResource = ({ bidPrice, depth, }: { - entityId: bigint; + entityId: ID; resource: Resources; active: boolean; onClick: (value: number) => void; @@ -75,8 +76,8 @@ export const MarketOrderPanel = ({ resourceAskOffers, resourceBidOffers, }: { - resourceId: number; - entityId: bigint; + resourceId: ResourcesIds; + entityId: ID; resourceAskOffers: MarketInterface[]; resourceBidOffers: MarketInterface[]; }) => { @@ -100,14 +101,14 @@ export const MarketOrderPanel = ({ ); }; -export const MarketOrders = ({ +const MarketOrders = ({ resourceId, entityId, isBuy = false, offers, }: { - resourceId: number; - entityId: bigint; + resourceId: ResourcesIds; + entityId: ID; isBuy?: boolean; offers: MarketInterface[]; }) => { @@ -148,7 +149,7 @@ export const MarketOrders = ({ ); }; -export const OrderRowHeader = ({ resourceId }: { resourceId?: number }) => { +const OrderRowHeader = ({ resourceId }: { resourceId?: number }) => { return (
qty.
@@ -169,7 +170,7 @@ export const OrderRowHeader = ({ resourceId }: { resourceId?: number }) => { ); }; -export const OrderRow = ({ offer, entityId, isBuy }: { offer: MarketInterface; entityId: bigint; isBuy: boolean }) => { +const OrderRow = ({ offer, entityId, isBuy }: { offer: MarketInterface; entityId: ID; isBuy: boolean }) => { const { computeTravelTime } = useTravel(); const { account: { account }, @@ -345,15 +346,15 @@ export const OrderRow = ({ offer, entityId, isBuy }: { offer: MarketInterface; e ); }; -export const OrderCreation = ({ +const OrderCreation = ({ initialBid, entityId, resourceId, isBuy = false, }: { initialBid: number; - entityId: bigint; - resourceId: number; + entityId: ID; + resourceId: ResourcesIds; isBuy?: boolean; }) => { const [loading, setLoading] = useState(false); @@ -454,11 +455,7 @@ export const OrderCreation = ({ {" "} {isBuy ? "Buy" : "Sell"}
- {/* {!isBuy ? ( */} setResource(Number(value))} /> - {/* // ) : ( - // setLords(Number(value))} /> - // )} */}
{currencyFormat(resourceBalance ? Number(resourceBalance) : 0, 0)} avail. @@ -477,11 +474,7 @@ export const OrderCreation = ({
Cost
- {/* {!isBuy ? ( */} setLords(Number(value))} /> - {/* // ) : ( - // setResource(Number(value))} /> - // )} */}
{currencyFormat(lordsBalance ? Number(lordsBalance) : 0, 0)} avail. diff --git a/client/src/ui/components/trading/MarketTradingHistory.tsx b/client/src/ui/components/trading/MarketTradingHistory.tsx index 5566d0d8c..af6bd1f3e 100644 --- a/client/src/ui/components/trading/MarketTradingHistory.tsx +++ b/client/src/ui/components/trading/MarketTradingHistory.tsx @@ -1,5 +1,5 @@ import { client } from "@/dojo/events/graphqlClient"; -import { ACCEPT_ORDER_EVENT, CANCEL_ORDER_EVENT, CREATE_ORDER_EVENT } from "@bibliothecadao/eternum"; +import { ACCEPT_ORDER_EVENT, CANCEL_ORDER_EVENT, CREATE_ORDER_EVENT, ID } from "@bibliothecadao/eternum"; import { useEffect, useState } from "react"; import { EventType, TradeHistoryEvent, TradeHistoryRowHeader } from "./TradeHistoryEvent"; @@ -7,15 +7,15 @@ const TAKER_INDEX = 1; const MAKER_INDEX = 2; interface MarketTradingHistoryProps { - realmEntityId: bigint; + realmEntityId: ID; } export type TradeEvent = { type: EventType; event: { - takerId: bigint; - makerId: bigint; - tradeId: bigint; + takerId: ID; + makerId: ID; + tradeId: ID; eventTime: Date; }; }; @@ -102,7 +102,7 @@ export const MarketTradingHistory = ({ realmEntityId }: MarketTradingHistoryProp const filterAndReturnTradeEvents = ( edges: any, - realmEntityId: bigint, + realmEntityId: ID, eventType: EventType, indexOfInterest: number, ): TradeEvent[] => { @@ -112,9 +112,9 @@ const filterAndReturnTradeEvents = ( return { type: eventType, event: { - takerId: BigInt(edge.node.keys[TAKER_INDEX]), - makerId: BigInt(edge.node.keys[MAKER_INDEX]), - tradeId: BigInt(edge.node.data[0]), + takerId: edge.node.keys[TAKER_INDEX], + makerId: edge.node.keys[MAKER_INDEX], + tradeId: edge.node.data[0], eventTime: new Date(parseInt(edge.node.data[1], 16) * 1000), }, }; diff --git a/client/src/ui/components/trading/Marketplace.tsx b/client/src/ui/components/trading/Marketplace.tsx deleted file mode 100644 index cc4e734db..000000000 --- a/client/src/ui/components/trading/Marketplace.tsx +++ /dev/null @@ -1,719 +0,0 @@ -import { getResourceBalance } from "@/hooks/helpers/useResources"; -import { useTravel } from "@/hooks/helpers/useTravel"; -import { - EternumGlobalConfig, - MarketInterface, - ResourcesIds, - findResourceById, - orderNameDict, - resources, -} from "@bibliothecadao/eternum"; -import clsx from "clsx"; -import { useMemo, useState } from "react"; -import * as realmsData from "../../../data/geodata/realms.json"; -import { useDojo } from "../../../hooks/context/DojoContext"; -import { useGetRealm } from "../../../hooks/helpers/useRealm"; -import { useGetMyOffers, useTrade } from "../../../hooks/helpers/useTrade"; -import useMarketStore from "../../../hooks/store/useMarketStore"; -import useRealmStore from "../../../hooks/store/useRealmStore"; -import useUIStore from "../../../hooks/store/useUIStore"; -import Button from "../../elements/Button"; -import { FilterButton } from "../../elements/FilterButton"; -import { FiltersPanel } from "../../elements/FiltersPanel"; -import { OrderIcon } from "../../elements/OrderIcon"; -import { ResourceIcon } from "../../elements/ResourceIcon"; -import { SortButton, SortInterface } from "../../elements/SortButton"; -import { SortPanel } from "../../elements/SortPanel"; -import TextInput from "../../elements/TextInput"; -import { currencyFormat, divideByPrecision } from "../../utils/utils"; - -interface MarketplaceProps { - onCreateOffer: (resourceId: number | null, isBuy: boolean) => void; - setSelectedTrade: (trade: MarketInterface | null) => void; -} - -interface DepthOfMarket { - price: number; - amount: number; -} - -interface ResourceOffersSummary { - resourceId: number; - bestPrice: number; - totalAmount: number; - totalOffers: number; - depthOfMarket: DepthOfMarket[]; -} - -export const Marketplace = ({ onCreateOffer, setSelectedTrade }: MarketplaceProps) => { - const [selectedResource, setSelectedResource] = useState(null); - const [isBuy, setIsBuy] = useState(false); - - const marketOffers = useMarketStore((state) => state.lordsMarket); - const myOffers = useGetMyOffers(); - - // @note: in open market, the current player will always be the taker so - // resourcesGet = takerGets - // resourcesGive = makerGets - - const bidOffers = useMemo(() => { - if (!marketOffers) return []; - - return [...marketOffers, ...myOffers].filter( - (offer) => offer.takerGets.length === 1 && offer.takerGets[0]?.resourceId === ResourcesIds["Lords"], - ); - }, [marketOffers, myOffers]); - - const selectedResourceBidOffers = useMemo(() => { - if (!bidOffers) return []; - - return bidOffers - .filter((offer) => (selectedResource ? offer.makerGets[0]?.resourceId === selectedResource : true)) - .sort((a, b) => b.ratio - a.ratio); - }, [bidOffers, selectedResource]); - - const bidOffersSummary = useMemo(() => { - if (!bidOffers) return []; - - const summary: ResourceOffersSummary[] = []; - - resources.forEach((resource) => { - if (resource.trait === "Lords") return; - - summary.push({ - resourceId: resource.id, - totalAmount: 0, - totalOffers: 0, - bestPrice: 0, - depthOfMarket: [] as DepthOfMarket[], - }); - }); - - bidOffers.forEach((offer) => { - offer.makerGets.forEach((resource) => { - const resourceIndex = summary.findIndex((summary) => summary.resourceId === resource.resourceId); - - if (resourceIndex >= 0) { - summary[resourceIndex].totalAmount += resource.amount; - summary[resourceIndex].totalOffers += 1; - summary[resourceIndex].bestPrice = Math.max( - summary[resourceIndex].bestPrice, - offer.takerGets[0].amount / resource.amount, - ); - const depthOfMarketIndex = summary[resourceIndex].depthOfMarket.findIndex( - (depth) => depth.price === offer.takerGets[0].amount / resource.amount, - ); - if (depthOfMarketIndex >= 0) { - summary[resourceIndex].depthOfMarket[depthOfMarketIndex].amount += resource.amount; - } else { - summary[resourceIndex].depthOfMarket.push({ - price: offer.takerGets[0].amount / resource.amount, - amount: resource.amount, - }); - } - } else { - summary.push({ - resourceId: resource.resourceId, - totalAmount: resource.amount, - totalOffers: 1, - bestPrice: resource.amount / offer.takerGets[0].amount, - depthOfMarket: [{ price: resource.amount / offer.takerGets[0].amount, amount: resource.amount }], - }); - } - }); - - summary.forEach((summary) => { - summary.depthOfMarket.sort((a, b) => b.price - a.price); - }); - }); - - return summary; - }, [bidOffers]); - - const askOffers = useMemo(() => { - if (!marketOffers) return []; - - return [...marketOffers, ...myOffers].filter( - (offer) => offer.takerGets.length === 1 && offer.makerGets[0]?.resourceId === ResourcesIds["Lords"], - ); - }, [marketOffers, myOffers]); - - const selectedResourceAskOffers = useMemo(() => { - if (!askOffers) return []; - - return askOffers - .filter((offer) => offer.takerGets[0].resourceId === selectedResource) - .sort((a, b) => b.ratio - a.ratio); - }, [askOffers, selectedResource]); - - const askOffersSummary = useMemo(() => { - if (!askOffers) return []; - - const summary: ResourceOffersSummary[] = []; - - resources.forEach((resource) => { - if (resource.trait === "Lords") return; - - summary.push({ - resourceId: resource.id, - totalAmount: 0, - totalOffers: 0, - bestPrice: Infinity, - depthOfMarket: [] as DepthOfMarket[], - }); - }); - - askOffers.forEach((offer) => { - offer.takerGets.forEach((resource) => { - const resourceIndex = summary.findIndex((summary) => summary.resourceId === resource.resourceId); - - if (resourceIndex >= 0) { - summary[resourceIndex].totalAmount += resource.amount; - summary[resourceIndex].totalOffers += 1; - summary[resourceIndex].bestPrice = Math.min( - summary[resourceIndex].bestPrice, - offer.makerGets[0].amount / resource.amount, - ); - - const depthOfMarketIndex = summary[resourceIndex].depthOfMarket.findIndex( - (depth) => depth.price === offer.makerGets[0].amount / resource.amount, - ); - - if (depthOfMarketIndex >= 0) { - summary[resourceIndex].depthOfMarket[depthOfMarketIndex].amount += resource.amount; - } else { - summary[resourceIndex].depthOfMarket.push({ - price: offer.makerGets[0].amount / resource.amount, - amount: resource.amount, - }); - } - } else { - summary.push({ - resourceId: resource.resourceId, - totalAmount: resource.amount, - totalOffers: 1, - bestPrice: resource.amount / offer.makerGets[0].amount, - depthOfMarket: [{ price: resource.amount / offer.makerGets[0].amount, amount: resource.amount }], - }); - } - }); - - summary.forEach((summary) => { - summary.depthOfMarket.sort((a, b) => a.price - b.price); - }); - }); - - return summary; - }, [askOffers]); - - return ( - <> - {selectedResource ? ( - setSelectedResource(null)} - onCreate={() => onCreateOffer(selectedResource, isBuy)} - setSelectedTrade={setSelectedTrade} - /> - ) : ( - { - setIsBuy(true); - setSelectedResource(resourceId); - }} - onSell={(resourceId: number) => { - setIsBuy(false); - setSelectedResource(resourceId); - }} - onCreate={() => onCreateOffer(selectedResource, isBuy)} - /> - )} - - ); -}; - -const MarketplaceOverviewPanel = ({ - onBuy, - onSell, - onCreate, - askOffersSummary, - bidOffersSummary, -}: { - onBuy: (resourceId: number) => void; - onSell: (resourceId: number) => void; - onCreate: () => void; - askOffersSummary: ResourceOffersSummary[]; - bidOffersSummary: ResourceOffersSummary[]; -}) => { - const [search, setSearch] = useState(""); - - const sortingParams = useMemo(() => { - return [ - { label: "Resource", sortKey: "resource", className: "w-[120px]" }, - { label: "Balance", sortKey: "balance", className: "w-[30px]" }, - { label: "Best Ask price", sortKey: "ask-price", className: "w-[100px] ml-auto !justify-end" }, - { label: "Ask Total Vol.", sortKey: "ask-vol", className: "ml-4 w-[100px] !justify-end" }, - { label: "Best Bid price", sortKey: "bid-price", className: "ml-4 w-[100px] !justify-end" }, - { label: "Bid Total Vol.", sortKey: "bid-vol", className: "ml-4 w-[100px] !justify-end" }, - ]; - }, []); - - const [activeSort, setActiveSort] = useState({ - sortKey: "number", - sort: "none", - }); - - // const sortedOffers = useMemo(() => sortTrades(offers, activeSort), [offers, activeSort]); - - const filteredResources = useMemo(() => { - return resources.filter((resource) => { - return resource.trait.toLowerCase().includes(search.toLowerCase()); - }); - }, [search]); - - return ( -
-
- - -
- - {sortingParams.map(({ label, sortKey, className }) => ( - { - setActiveSort({ - sortKey: _sortKey, - sort: _sort, - }); - }} - /> - ))} - -
- {filteredResources.map((resource) => { - if (resource.trait === "Lords") return null; - return ( - summary.resourceId === resource.id)} - bidSummary={bidOffersSummary.find((summary) => summary.resourceId === resource.id)} - onBuy={() => onBuy(resource.id)} - onSell={() => onSell(resource.id)} - /> - ); - })} -
-
- ); -}; - -const OverviewResourceRow = ({ - askSummary, - bidSummary, - onBuy, - onSell, -}: { - askSummary: ResourceOffersSummary | undefined; - bidSummary: ResourceOffersSummary | undefined; - onBuy: () => void; - onSell: () => void; -}) => { - const { - setup: { - components: { Resource }, - }, - } = useDojo(); - - const resource = findResourceById(bidSummary?.resourceId || 0); - const realmEntityId = useRealmStore((state) => state.realmEntityId); - const setTooltip = useUIStore((state) => state.setTooltip); - - const { getBalance } = getResourceBalance(); - - const realmResource = useMemo(() => { - return getBalance(realmEntityId!, askSummary?.resourceId || 0); - }, [realmEntityId, askSummary?.resourceId]); - - const depthOfMarketBids = useMemo(() => { - const lastFive = bidSummary?.depthOfMarket.slice(0, 5) || []; - - let accumulatedAmount = 0; - - return ( - lastFive.length && ( -
- {resource && ( -
- - {resource.trait} -
- )} - {bidSummary && - lastFive.map((depth) => { - accumulatedAmount += depth.amount; - const width = (accumulatedAmount / bidSummary.totalAmount) * 100; - return ( -
-
-
- {Intl.NumberFormat("en-US", { - style: "decimal", - maximumFractionDigits: 2, - minimumFractionDigits: 2, - }).format(divideByPrecision(depth.amount))} -
-
- {depth.price.toFixed(2)} - -
-
-
-
- ); - })} -
- ) - ); - }, [bidSummary?.depthOfMarket]); - - const depthOfMarketAsks = useMemo(() => { - const lastFive = askSummary?.depthOfMarket.slice(0, 5) || []; - - let accumulatedAmount = 0; - - return ( - lastFive.length && ( -
- {resource && ( -
- - {resource.trait} -
- )} - {askSummary && - lastFive.map((depth, i) => { - accumulatedAmount += depth.amount; - const width = (accumulatedAmount / askSummary.totalAmount) * 100; - return ( -
-
-
- {Intl.NumberFormat("en-US", { - style: "decimal", - maximumFractionDigits: 2, - minimumFractionDigits: 2, - }).format(divideByPrecision(depth.amount))} -
-
- {depth.price.toFixed(2)} - -
-
-
-
- ); - })} -
- ) - ); - }, [askSummary?.depthOfMarket]); - - return ( -
- {resource && ( -
- -
{resource.trait}
-
- )} -
-
{currencyFormat(Number(realmResource?.balance || 0), 0)}
-
-
- setTooltip({ - position: "bottom", - content: depthOfMarketAsks, - }) - } - onMouseLeave={() => setTooltip(null)} - > - {askSummary && askSummary.bestPrice !== Infinity ? askSummary.bestPrice.toFixed(2) : (0).toFixed(2)} - -
-
- setTooltip({ - position: "bottom", - content: depthOfMarketAsks, - }) - } - onMouseLeave={() => setTooltip(null)} - > - {Intl.NumberFormat("en-US", { - style: "decimal", - maximumFractionDigits: 2, - minimumFractionDigits: 2, - }).format(divideByPrecision(askSummary?.totalAmount || 0))} - -
-
- setTooltip({ - position: "bottom", - content: depthOfMarketBids, - }) - } - onMouseLeave={() => setTooltip(null)} - > - {bidSummary && bidSummary.bestPrice !== Infinity ? bidSummary.bestPrice.toFixed(2) : (0).toFixed(2)} - -
-
- setTooltip({ - position: "bottom", - content: depthOfMarketBids, - }) - } - onMouseLeave={() => setTooltip(null)} - > - {Intl.NumberFormat("en-US", { - style: "decimal", - maximumFractionDigits: 2, - minimumFractionDigits: 2, - }).format(divideByPrecision(bidSummary?.totalAmount || 0))} - -
-
- ); -}; - -const MarketplaceResourceOffersPanel = ({ - offers, - isBuy, - onCreate, - resourceId, - onBack, - setSelectedTrade, -}: { - offers: MarketInterface[]; - isBuy: boolean; - onCreate: () => void; - resourceId: number; - onBack: () => void; - setSelectedTrade: (trade: MarketInterface | null) => void; -}) => { - const realmEntityId = useRealmStore((state) => state.realmEntityId); - - const sortingParams = useMemo(() => { - return [ - { label: "Sell", sortKey: "sell", className: "" }, - { label: "Price", sortKey: "Price", className: "ml-auto" }, - { label: "Buy", sortKey: "buy", className: "ml-auto" }, - { label: "Order", sortKey: "order", className: "ml-auto" }, - { label: "Travel time", sortKey: "travel", className: "ml-auto" }, - ]; - }, []); - - const [activeSort, setActiveSort] = useState({ - sortKey: "number", - sort: "none", - }); - - return ( - <> -
-
- - - Resource: {findResourceById(resourceId)?.trait} - - - Type: -
- {isBuy ? "Buy" : "Sell"} -
-
-
- -
- - {sortingParams.map(({ label, sortKey, className }) => ( - { - setActiveSort({ - sortKey: _sortKey, - sort: _sort, - }); - }} - /> - ))} - -
- {offers.map((offer) => ( - setSelectedTrade(offer)} - /> - ))} -
-
- - ); -}; - -const ResourceOfferRow = ({ - realmEntityId, - offer, - isBuy, - onClick, -}: { - realmEntityId: bigint; - offer: MarketInterface; - isBuy: boolean; - onClick: () => void; -}) => { - const { - account: { account }, - setup: { - systemCalls: { cancel_order }, - }, - } = useDojo(); - const { makerGets, takerGets } = offer; - const resource = findResourceById(isBuy ? offer.takerGets[0].resourceId : offer.makerGets[0].resourceId); - const { realm: makerRealm } = useGetRealm(offer.makerId); - const { computeTravelTime } = useTravel(); - - const [isLoading, setIsLoading] = useState(false); - - const { canAcceptOffer } = useTrade(); - - const canAccept = useMemo(() => { - return canAcceptOffer({ realmEntityId, resourcesGive: makerGets }); - }, [realmEntityId, makerGets]); - - const onCancel = async () => { - setIsLoading(true); - await cancel_order({ - signer: account, - trade_id: offer.tradeId, - return_resources: takerGets.flatMap(({ resourceId, amount }) => [resourceId, amount]), - }).finally(() => setIsLoading(false)); - }; - - const travelTime = useMemo( - () => computeTravelTime(realmEntityId, offer.makerId, EternumGlobalConfig.speed.donkey, true) || 0, - [realmEntityId, offer], - ); - - return ( -
- {resource && ( -
- - {divideByPrecision(offer.makerGets[0].amount)} -
- )} -
-
- {isBuy ? (1 / offer.ratio).toFixed(2) : offer.ratio.toFixed(2)} -
-
- {resource && ( -
- {divideByPrecision(offer.takerGets[0].amount)} - -
- )} - - {makerRealm && ( -
- {} - {realmsData["features"][Number(makerRealm.realmId - 1n)]?.name} -
- )} - {offer.makerId !== realmEntityId && ( -
- {`${Math.floor(travelTime / 60)} hrs ${travelTime % 60} mins`} - -
- )} - {offer.makerId === realmEntityId && ( -
- -
- )} -
- ); -}; diff --git a/client/src/ui/components/trading/ResourceArrivals.tsx b/client/src/ui/components/trading/ResourceArrivals.tsx index ec91505cd..fac94fc32 100644 --- a/client/src/ui/components/trading/ResourceArrivals.tsx +++ b/client/src/ui/components/trading/ResourceArrivals.tsx @@ -2,8 +2,9 @@ import { Entity } from "../entities/Entity"; import { Headline } from "@/ui/elements/Headline"; import { HintModalButton } from "@/ui/elements/HintModalButton"; import { HintSection } from "../hints/HintModal"; +import { ID } from "@bibliothecadao/eternum"; -export const AllResourceArrivals = ({ entityIds }: { entityIds: bigint[] }) => { +export const AllResourceArrivals = ({ entityIds }: { entityIds: ID[] }) => { return (
diff --git a/client/src/ui/components/trading/TradeHistoryEvent.tsx b/client/src/ui/components/trading/TradeHistoryEvent.tsx index e502a2ffe..d6bfc05b2 100644 --- a/client/src/ui/components/trading/TradeHistoryEvent.tsx +++ b/client/src/ui/components/trading/TradeHistoryEvent.tsx @@ -1,3 +1,4 @@ +import { ClientComponents } from "@/dojo/createClientComponents"; import { useDojo } from "@/hooks/context/DojoContext"; import { getEntitiesUtils } from "@/hooks/helpers/useEntities"; import { getResourceBalance } from "@/hooks/helpers/useResources"; @@ -5,7 +6,7 @@ import useBlockchainStore from "@/hooks/store/useBlockchainStore"; import { ResourceIcon } from "@/ui/elements/ResourceIcon"; import { currencyIntlFormat } from "@/ui/utils/utils"; import { EternumGlobalConfig, ResourcesIds } from "@bibliothecadao/eternum"; -import { ComponentValue, getComponentValue, Type } from "@dojoengine/recs"; +import { ComponentValue, getComponentValue } from "@dojoengine/recs"; import { getEntityIdFromKeys } from "@dojoengine/utils"; import { TradeEvent } from "./MarketTradingHistory"; @@ -25,7 +26,7 @@ const colors = { [EventType.BOUGHT]: "text-green", }; -export enum TradeStatus { +enum TradeStatus { OPEN = 0, ACCEPTED = 1, CANCELLED = 2, @@ -53,7 +54,7 @@ export const TradeHistoryEvent = ({ trade }: { trade: TradeEvent }) => { const { nextBlockTimestamp } = useBlockchainStore(); const { getAddressNameFromEntity } = getEntitiesUtils(); - const tradeComponent = getComponentValue(Trade, getEntityIdFromKeys([trade.event.tradeId])); + const tradeComponent = getComponentValue(Trade, getEntityIdFromKeys([BigInt(trade.event.tradeId)])); const eventType = trade.type === EventType.ORDER_CREATED && nextBlockTimestamp! > tradeComponent!.expires_at ? EventType.ORDER_EXPIRED @@ -75,7 +76,7 @@ export const TradeHistoryEvent = ({ trade }: { trade: TradeEvent }) => { : getResourcesBalance(tradeComponent!.taker_gives_resources_id); const expirationDate = - trade.type === EventType.ORDER_CREATED ? new Date(tradeComponent!.expires_at * 1000) : undefined; + trade.type === EventType.ORDER_CREATED ? new Date(Number(tradeComponent!.expires_at) * 1000) : undefined; const price = getPrice(resourceGiven[0], resourceTaken[0]); @@ -111,28 +112,8 @@ export const TradeHistoryEvent = ({ trade }: { trade: TradeEvent }) => { }; const getPrice = ( - resourceA: - | ComponentValue< - { - entity_id: Type.BigInt; - index: Type.Number; - resource_type: Type.Number; - resource_amount: Type.BigInt; - }, - unknown - > - | undefined, - resourceB: - | ComponentValue< - { - entity_id: Type.BigInt; - index: Type.Number; - resource_type: Type.Number; - resource_amount: Type.BigInt; - }, - unknown - > - | undefined, + resourceA: ComponentValue | undefined, + resourceB: ComponentValue | undefined, ): Number => { if (resourceA!.resource_type === ResourcesIds.Lords) { return Number(resourceA!.resource_amount) / Number(resourceB!.resource_amount); diff --git a/client/src/ui/components/trading/TransferBetweenEntities.tsx b/client/src/ui/components/trading/TransferBetweenEntities.tsx index fe171ea10..f2c1fd350 100644 --- a/client/src/ui/components/trading/TransferBetweenEntities.tsx +++ b/client/src/ui/components/trading/TransferBetweenEntities.tsx @@ -10,7 +10,7 @@ import { NumberInput } from "@/ui/elements/NumberInput"; import { ResourceCost } from "@/ui/elements/ResourceCost"; import TextInput from "@/ui/elements/TextInput"; import { divideByPrecision, multiplyByPrecision } from "@/ui/utils/utils"; -import { EternumGlobalConfig, resources } from "@bibliothecadao/eternum"; +import { EternumGlobalConfig, ID, resources } from "@bibliothecadao/eternum"; import clsx from "clsx"; import { ArrowRight, LucideArrowRight } from "lucide-react"; import { useEffect, useMemo, useState } from "react"; @@ -39,7 +39,7 @@ const STEPS = [ interface SelectedEntity { name: string; - entityId: bigint; + entityId: ID; } export const TransferBetweenEntities = ({ entitiesList }: { entitiesList: { entities: any[]; name: string }[] }) => { @@ -117,11 +117,11 @@ export const TransferBetweenEntities = ({ entitiesList }: { entitiesList: { enti }); }; - const isEntitySelected = (entities: any[], selectedEntityId: bigint | undefined) => { + const isEntitySelected = (entities: any[], selectedEntityId: ID | undefined) => { return entities.some((entity) => entity.entity_id === selectedEntityId); }; - const filterEntities = (entities: any[], searchTerm: string, selectedEntityId: bigint | undefined) => { + const filterEntities = (entities: any[], searchTerm: string, selectedEntityId: ID | undefined) => { return entities.filter( (entity) => entity.entity_id === selectedEntityId || @@ -138,12 +138,6 @@ export const TransferBetweenEntities = ({ entitiesList }: { entitiesList: { enti {selectedEntityIdFrom?.toString() && selectedEntityIdTo?.toString() && ( <>
Transfer From: {selectedEntityIdFrom?.name}
- {/*
- {" "} - -
*/}
Transfer To: {selectedEntityIdTo?.name}
@@ -287,9 +281,9 @@ const SelectEntityFromList = ({ selectedCounterpartyId, entities, }: { - onSelect: (name: string, entityId: bigint) => void; - selectedEntityId: bigint | null; - selectedCounterpartyId: bigint | null; + onSelect: (name: string, entityId: ID) => void; + selectedEntityId: ID | null; + selectedCounterpartyId: ID | null; entities: any[]; }) => { const { getRealmAddressName } = useRealm(); @@ -335,7 +329,7 @@ const SelectResources = ({ setSelectedResourceIds: any; selectedResourceAmounts: any; setSelectedResourceAmounts: any; - entity_id: bigint; + entity_id: ID; }) => { const { getBalance } = getResourceBalance(); const { playResourceSound } = usePlayResourceSound(); diff --git a/client/src/ui/components/worldmap/Arcs.jsx b/client/src/ui/components/worldmap/Arcs.jsx deleted file mode 100644 index 214e2bbb6..000000000 --- a/client/src/ui/components/worldmap/Arcs.jsx +++ /dev/null @@ -1,66 +0,0 @@ -import * as THREE from "three"; -import { useFrame } from "@react-three/fiber"; -import { useMemo, useRef } from "react"; -import { Trail } from "@react-three/drei"; - -const material = new THREE.MeshBasicMaterial({ color: "orangered" }); -const sphere = new THREE.SphereGeometry(0.1, 32, 32); - -const Arcs = ({ paths }) => { - const spheresRefs = useRef([]); - - const curves = useMemo( - () => - paths.map((path, i) => { - const point_1 = new THREE.Vector3(-path.from.x, -0.3, -path.from.y); - const point_2 = new THREE.Vector3(-path.to.x, -0.3, -path.to.y); - const pathLength = point_1.distanceTo(point_2); - const pointBetweenFromAndTo = new THREE.Vector3( - (-path.from.x + -path.to.x) / 2, - Math.max(pathLength / 2, 3), - (-path.from.y + -path.to.y) / 2, - ); - return new THREE.QuadraticBezierCurve3(point_1, pointBetweenFromAndTo, point_2); - }), - [paths], - ); - - let t = 0; - useFrame(() => { - spheresRefs.current.forEach((sphereRef, i) => { - sphereRef.position.copy(curves[i].getPointAt(t)); - }); - t += 0.0025; - if (t >= 1) t = 0; - }); - - return ( - <> - {curves.map((curve, i) => { - return ( - width} // A function to define the width in each point along it. - > - (spheresRefs.current[i] = el)} - position={[0, 0, 0]} - geometry={sphere} - material={material} - /> - - ); - })} - - ); -}; - -export default Arcs; diff --git a/client/src/ui/components/worldmap/Compass.tsx b/client/src/ui/components/worldmap/Compass.tsx deleted file mode 100644 index 6d69cbc45..000000000 --- a/client/src/ui/components/worldmap/Compass.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import useUIStore from "../../../hooks/store/useUIStore"; - -export const Compass = () => { - const direction = useUIStore((state) => state.compassDirection); - - return ( -
-
-
-
- -
- N -
-
- E -
-
- S -
-
- W -
-
-
- ); -}; diff --git a/client/src/ui/components/worldmap/ExploreNotification.tsx b/client/src/ui/components/worldmap/ExploreNotification.tsx deleted file mode 100644 index a9e37c96b..000000000 --- a/client/src/ui/components/worldmap/ExploreNotification.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import { useEffect } from "react"; -import { ResourceIcon } from "../../elements/ResourceIcon"; -import { useExplore } from "../../../hooks/helpers/useExplore"; -import { biomes, findResourceById } from "@bibliothecadao/eternum"; -import { divideByPrecision } from "../../utils/utils"; -import clsx from "clsx"; -import { useNotificationsStore } from "../../../hooks/store/useNotificationsStore"; -import { useAutoAnimate } from "@formkit/auto-animate/react"; - -const BIOMES = biomes as Record; - -export const ExploreNotifications = () => { - const exploreNotification = useNotificationsStore((state) => state.exploreNotification); - const setExploreNotification = useNotificationsStore((state) => state.setExploreNotification); - const [parent] = useAutoAnimate(/* optional config */); - - const { useFoundResources } = useExplore(); - let { foundResources, setFoundResources } = useFoundResources(exploreNotification?.entityId); - - useEffect(() => { - if (exploreNotification) { - setTimeout(() => { - setExploreNotification(null); - setFoundResources(undefined); - }, 5000); - } - }, [exploreNotification]); - - return ( -
- {exploreNotification && foundResources && ( -
- -
-
- You found{" "} - - {BIOMES[exploreNotification.biome].name}! - -
-
- and -
- + - {Intl.NumberFormat("en-US", { - notation: "compact", - maximumFractionDigits: 1, - }).format(divideByPrecision(Number(foundResources?.amount)) || 0)} -
- {foundResources && ( - - )} -
-
- -
- )} -
- ); -}; diff --git a/client/src/ui/components/worldmap/Minimap.tsx b/client/src/ui/components/worldmap/Minimap.tsx deleted file mode 100644 index c7c0bb6cd..000000000 --- a/client/src/ui/components/worldmap/Minimap.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import useUIStore from "@/hooks/store/useUIStore"; -import { MapControls } from "@react-three/drei"; -import { Canvas, useFrame, useThree } from "@react-three/fiber"; -import { useRef } from "react"; -import { Mesh, Vector3 } from "three"; - -// MINIMAP - -// TODO: We need to scale the minimap the same way we scale the actual map -// Clicking the minimap should take you to that location on the map -// Should the minimap be small hexes? or just a mesh with a texture? - -export const MiniMap = () => { - return ( - - - - - - ); -}; - -export const MiniMapMesh = () => { - const setCameraTarget = useUIStore((state) => state.setCameraTarget); - - const { mouse, camera, raycaster } = useThree(); - - const mesh = useRef(null); - - const actualMapWidth = 100000; - const actualMapHeight = 100000; - - // Define the scale factors if the minimap is not a 1:1 representation of the actual map - const scaleX = actualMapWidth / 100; - const scaleY = actualMapHeight / 100; - - const handleClick = (event: any) => { - // Update the raycaster with the current mouse and camera information - raycaster.setFromCamera(mouse, camera); - - // Assuming the minimap is on the XZ plane and Y is up, intersect with a plane at Y=0 - const planeIntersect = raycaster.intersectObject(mesh.current); - - if (planeIntersect.length > 0) { - // Get the point of intersection - const point = planeIntersect[0].point; - - console.log("Clicked on minimap at", point.x, point.z); - - // Update the camera position in your state - setCameraTarget(new Vector3(point.x, point.y, point.z)); - // setCameraPosition( - // new Vector3(point.x + (50 * Math.random() < 1 ? 1 : -1), 35, point.z + 50 * Math.random() < 1 ? 1 : -1), - // ); - } - }; - - return ( - - - - - ); -}; diff --git a/client/src/ui/components/worldmap/armies/Army.tsx b/client/src/ui/components/worldmap/armies/Army.tsx index 682395261..9757b200b 100644 --- a/client/src/ui/components/worldmap/armies/Army.tsx +++ b/client/src/ui/components/worldmap/armies/Army.tsx @@ -60,7 +60,7 @@ export const Army = React.memo(({ army }: ArmyProps & JSX.IntrinsicElements["gro ); }, arePropsEqual); -export const ArmySelectionOverlay = ({ army }: ArmyProps) => { +const ArmySelectionOverlay = ({ army }: ArmyProps) => { const selectedEntity = useUIStore((state) => state.selectedEntity); const armyPosition: Position = { x: army.position.x, y: army.position.y }; diff --git a/client/src/ui/components/worldmap/armies/ArmyFlag.tsx b/client/src/ui/components/worldmap/armies/ArmyFlag.tsx index aa693098d..1f4f1deac 100644 --- a/client/src/ui/components/worldmap/armies/ArmyFlag.tsx +++ b/client/src/ui/components/worldmap/armies/ArmyFlag.tsx @@ -15,7 +15,7 @@ export const ArmyFlag = ({ }) => { const realms = useRealmStore((state) => state.realmEntityIds); const realmOrder = useMemo(() => { - const realmId = realms[0]?.realmId || BigInt(0); + const realmId = realms[0]?.realmId || 0; const orderName = getRealmOrderNameById(realmId); return orderName.charAt(0).toUpperCase() + orderName.slice(1); }, []); diff --git a/client/src/ui/components/worldmap/armies/ArmyInfoLabel.tsx b/client/src/ui/components/worldmap/armies/ArmyInfoLabel.tsx index a5a3e779f..4a9f4d454 100644 --- a/client/src/ui/components/worldmap/armies/ArmyInfoLabel.tsx +++ b/client/src/ui/components/worldmap/armies/ArmyInfoLabel.tsx @@ -6,11 +6,11 @@ import { BaseThreeTooltip, Position } from "@/ui/elements/BaseThreeTooltip"; import { Headline } from "@/ui/elements/Headline"; import { ResourceIcon } from "@/ui/elements/ResourceIcon"; import { StaminaResource } from "@/ui/elements/StaminaResource"; +import { formatSecondsLeftInDaysHours } from "@/ui/utils/utils"; import clsx from "clsx"; import { useMemo } from "react"; import { useRealm } from "../../../../hooks/helpers/useRealm"; import { getRealmNameById } from "../../../utils/realms"; -import { formatSecondsLeftInDaysHours } from "../../cityview/realm/labor/laborUtils"; import { InventoryResources } from "../../resources/InventoryResources"; interface ArmyInfoLabelProps { @@ -46,7 +46,7 @@ const RaiderInfo = ({ army }: ArmyInfoLabelProps) => { [arrivalTime?.arrives_at, nextBlockTimestamp], ); - const realmId = realm?.realm_id || 0n; + const realmId = realm?.realm_id || 0; const attackerAddressName = entityOwner ? getRealmAddressName(entityOwner.entity_owner_id) : ""; @@ -80,7 +80,7 @@ const RaiderInfo = ({ army }: ArmyInfoLabelProps) => { {arrivalTime && arrivalTime.arrives_at !== undefined && isTraveling && nextBlockTimestamp && (
{isPassiveTravel - ? formatSecondsLeftInDaysHours(arrivalTime.arrives_at - nextBlockTimestamp) + ? formatSecondsLeftInDaysHours(Number(arrivalTime.arrives_at) - nextBlockTimestamp) : "Arrives Next Tick"} {army.battle_id ? `In Battle` : ""}
diff --git a/client/src/ui/components/worldmap/armies/ArmyMenu.tsx b/client/src/ui/components/worldmap/armies/ArmyMenu.tsx deleted file mode 100644 index 67a4b899a..000000000 --- a/client/src/ui/components/worldmap/armies/ArmyMenu.tsx +++ /dev/null @@ -1,166 +0,0 @@ -import { ReactComponent as InfoIcon } from "@/assets/icons/common/info.svg"; -import { ArmyMode } from "@/hooks/store/_mapStore"; -import Button from "@/ui/elements/Button"; -import { DojoHtml } from "@/ui/elements/DojoHtml"; -import { EXPLORATION_COSTS, type Resource } from "@bibliothecadao/eternum"; -import { getComponentValue } from "@dojoengine/recs"; -import clsx from "clsx"; -import { useEffect, useMemo, useState } from "react"; -import { useDojo } from "../../../../hooks/context/DojoContext"; -import { getResourceBalance } from "../../../../hooks/helpers/useResources"; -import useBlockchainStore from "../../../../hooks/store/useBlockchainStore"; -import useUIStore from "../../../../hooks/store/useUIStore"; -import { ResourceCost } from "../../../elements/ResourceCost"; -import { getEntityIdFromKeys } from "../../../utils/utils"; - -const EXPLORE_DESCRIPTION = "Explore the area to discover resources. Limit: 1 hex per tick."; -const TRAVEL_DESCRIPTION = "Move to a new location. Limit: 5 hexes per tick."; - -const ArmyActionInfo = ({ - entityId, - costs, - description, -}: { - entityId: bigint; - costs: Resource[]; - description?: string; -}) => { - const { getBalance } = getResourceBalance(); - - return ( -
- {description &&
{description}
} - {costs.length > 0 && ( - <> -
Cost
-
- {costs.map((resource, index) => { - const balance = getBalance(entityId || 0n, resource.resourceId); - return ( - - ); - })} -
- - )} -
- ); -}; - -export const ArmyMenu = ({ selectedEntityId }: { selectedEntityId: bigint }) => { - const { - account: { account }, - setup: { - components: { ArrivalTime, EntityOwner, Owner }, - }, - } = useDojo(); - - const [appeared, setAppeared] = useState(false); - - const armyMode = useUIStore((state) => state.armyMode); - const [playerOwnsSelectedEntity, setPlayerOwnsSelectedEntity] = useState(false); - - const nextBlockTimestamp = useBlockchainStore((state) => state.nextBlockTimestamp); - - useEffect(() => { - const fetchEntityDetails = () => { - const owner = getComponentValue(EntityOwner, getEntityIdFromKeys([selectedEntityId])) || undefined; - const entityOwner = - getComponentValue(Owner, getEntityIdFromKeys([BigInt(owner?.entity_owner_id || "0")])) || undefined; - const isPlayerOwner = entityOwner?.address === BigInt(account.address); - setPlayerOwnsSelectedEntity(isPlayerOwner); - }; - - fetchEntityDetails(); - }, [selectedEntityId, account.address]); - - const arrivalTime = getComponentValue(ArrivalTime, getEntityIdFromKeys([selectedEntityId])); - const entityOwner = getComponentValue(EntityOwner, getEntityIdFromKeys([selectedEntityId])); - - const isPassiveTravel = useMemo( - () => arrivalTime && nextBlockTimestamp && arrivalTime.arrives_at > nextBlockTimestamp, - [arrivalTime, nextBlockTimestamp], - ); - - const isTraveling = useMemo(() => isPassiveTravel, [isPassiveTravel]); - - const setTooltip = useUIStore((state) => state.setTooltip); - - const { getFoodResources } = getResourceBalance(); - - const explorationCosts = useMemo(() => { - const foodBalance = entityOwner ? getFoodResources(entityOwner.entity_owner_id) : []; - return EXPLORATION_COSTS.map((res) => ({ - ...res, - hasEnough: (foodBalance.find((food) => food.resourceId === res.resourceId)?.amount || 0) >= res.amount, - })); - }, [entityOwner, getFoodResources]); - - useEffect(() => { - const timer = setTimeout(() => setAppeared(true), 150); - return () => clearTimeout(timer); - }, []); - - return ( - -
- - - {playerOwnsSelectedEntity && ( - - )} -
-
- ); -}; diff --git a/client/src/ui/components/worldmap/guilds/GuildInvites.tsx b/client/src/ui/components/worldmap/guilds/GuildInvites.tsx index 03819bc71..cfe897c8b 100644 --- a/client/src/ui/components/worldmap/guilds/GuildInvites.tsx +++ b/client/src/ui/components/worldmap/guilds/GuildInvites.tsx @@ -1,14 +1,15 @@ -import { useMemo, useState, useCallback } from "react"; +import { useCallback, useMemo, useState } from "react"; import { useDojo } from "../../../../hooks/context/DojoContext"; +import Button from "../../../elements/Button"; import { SortButton, SortInterface } from "../../../elements/SortButton"; import { SortPanel } from "../../../elements/SortPanel"; -import Button from "../../../elements/Button"; -import { useGuilds, AddressWhitelistAndName, GuildWhitelistAndName } from "../../../../hooks/helpers/useGuilds"; -import { hasGuild } from "./utils"; -import { GuildMembers } from "./GuildMembers"; import { sortItems } from "@/ui/utils/utils"; +import { ContractAddress, ID } from "@bibliothecadao/eternum"; +import { AddressWhitelistAndName, GuildWhitelistAndName, useGuilds } from "../../../../hooks/helpers/useGuilds"; +import { GuildMembers } from "./GuildMembers"; import { SelectedGuildInterface } from "./Guilds"; +import { hasGuild } from "./utils"; type GuildWhitelistAndNameKeys = keyof GuildWhitelistAndName; interface SortingParamGuildWhitelistAndName { @@ -26,12 +27,12 @@ export const GuildInvites = () => { } = useDojo(); const [isLoading, setIsLoading] = useState(false); - const [selectedGuild, setSelectedGuild] = useState({ guildEntityId: 0n, name: "" }); + const [selectedGuild, setSelectedGuild] = useState({ guildEntityId: 0, name: "" }); const { getAddressWhitelist, getAddressGuild } = useGuilds(); - const { addressWhitelist } = getAddressWhitelist(BigInt(account.address)); - const { userGuildEntityId } = getAddressGuild(account.address); + const { addressWhitelist } = getAddressWhitelist(ContractAddress(account.address)); + const { userGuildEntityId } = getAddressGuild(ContractAddress(account.address)); const sortingParams: SortingParamGuildWhitelistAndName[] = useMemo(() => { return [{ label: "Guild Name", sortKey: "name", className: "col-span-1" }]; @@ -42,12 +43,12 @@ export const GuildInvites = () => { sort: "none", }); - const joinGuild = useCallback((guildEntityId: bigint) => { + const joinGuild = useCallback((guildEntityId: ID) => { setIsLoading(true); join_guild({ guild_entity_id: guildEntityId, signer: account }).finally(() => setIsLoading(false)); }, []); - const removePlayerFromWhitelist = useCallback((guildEntityId: bigint) => { + const removePlayerFromWhitelist = useCallback((guildEntityId: ID) => { setIsLoading(true); remove_player_from_whitelist({ player_address_to_remove: account.address, @@ -64,7 +65,7 @@ export const GuildInvites = () => {
-
@@ -120,9 +121,7 @@ export const GuildInvites = () => { diff --git a/client/src/ui/components/worldmap/guilds/GuildMembers.tsx b/client/src/ui/components/worldmap/guilds/GuildMembers.tsx index 824daa270..8eeee73a9 100644 --- a/client/src/ui/components/worldmap/guilds/GuildMembers.tsx +++ b/client/src/ui/components/worldmap/guilds/GuildMembers.tsx @@ -1,4 +1,5 @@ import { copyPlayerAddressToClipboard, displayAddress, sortItems } from "@/ui/utils/utils"; +import { ContractAddress } from "@bibliothecadao/eternum"; import { useCallback, useMemo, useState } from "react"; import { useDojo } from "../../../../hooks/context/DojoContext"; import { GuildMemberAndName, useGuilds } from "../../../../hooks/helpers/useGuilds"; @@ -47,7 +48,7 @@ export const GuildMembers = ({ selectedGuild, isOwner, ownerAddress }: GuildMemb sort: "none", }); - const removeGuildMember = useCallback((address: bigint) => { + const removeGuildMember = useCallback((address: ContractAddress) => { setIsLoading(true); remove_guild_member({ player_address_to_remove: address, @@ -88,17 +89,23 @@ export const GuildMembers = ({ selectedGuild, isOwner, ownerAddress }: GuildMemb

{member.name}

copyPlayerAddressToClipboard(BigInt(member.guildMember.address), member.name)} + onClick={() => copyPlayerAddressToClipboard(member.guildMember.address, member.name)} > {displayAddress(member.playerAddress)}

- {isOwner && member.playerAddress != account.address && guildOwner?.address == BigInt(account.address) && ( -
- -
- )} + {isOwner && + member.playerAddress != account.address && + guildOwner?.address == ContractAddress(account.address) && ( +
+ +
+ )}
); })} diff --git a/client/src/ui/components/worldmap/guilds/Guilds.tsx b/client/src/ui/components/worldmap/guilds/Guilds.tsx index 9b1ba630f..bb91d1c1e 100644 --- a/client/src/ui/components/worldmap/guilds/Guilds.tsx +++ b/client/src/ui/components/worldmap/guilds/Guilds.tsx @@ -10,6 +10,7 @@ import { ComponentValue } from "@dojoengine/recs"; import { GuildAndName, useGuilds } from "../../../../hooks/helpers/useGuilds"; import { GuildMembers } from "./GuildMembers"; import { hasGuild } from "./utils"; +import { ContractAddress, ID } from "@bibliothecadao/eternum"; type GuildAndNameKeys = keyof (ComponentValue & { name: string; @@ -22,7 +23,7 @@ interface SortingParamGuildAndName { } export interface SelectedGuildInterface { - guildEntityId: bigint; + guildEntityId: ID; name: string; } @@ -35,12 +36,12 @@ export const Guilds = () => { } = useDojo(); const [_, setIsLoading] = useState(false); - const [selectedGuild, setSelectedGuild] = useState({ guildEntityId: 0n, name: "" }); + const [selectedGuild, setSelectedGuild] = useState({ guildEntityId: 0, name: "" }); const { getGuilds, getAddressGuild } = useGuilds(); const { guilds } = getGuilds(); - const { userGuildEntityId, isOwner } = getAddressGuild(account.address); + const { userGuildEntityId, isOwner } = getAddressGuild(ContractAddress(account.address)); const sortingParams: SortingParamGuildAndName[] = useMemo(() => { return [ @@ -56,7 +57,7 @@ export const Guilds = () => { sort: "none", }); - const joinGuild = useCallback((guildEntityId: bigint) => { + const joinGuild = useCallback((guildEntityId: ID) => { setIsLoading(true); join_guild({ guild_entity_id: guildEntityId, signer: account }).finally(() => setIsLoading(false)); }, []); @@ -67,7 +68,7 @@ export const Guilds = () => { <>
-
diff --git a/client/src/ui/components/worldmap/guilds/MyGuild.tsx b/client/src/ui/components/worldmap/guilds/MyGuild.tsx index 1f39fbebf..09b03b0a1 100644 --- a/client/src/ui/components/worldmap/guilds/MyGuild.tsx +++ b/client/src/ui/components/worldmap/guilds/MyGuild.tsx @@ -1,14 +1,14 @@ -import { useState, useMemo, useCallback } from "react"; +import { SelectBox } from "@/ui/elements/SelectBox"; +import TextInput from "@/ui/elements/TextInput"; +import { ContractAddress, MAX_NAME_LENGTH } from "@bibliothecadao/eternum"; +import { useCallback, useMemo, useState } from "react"; import { useDojo } from "../../../../hooks/context/DojoContext"; import Button from "../../../elements/Button"; -import TextInput from "@/ui/elements/TextInput"; -import { SelectBox } from "@/ui/elements/SelectBox"; import { Tabs } from "../../../elements/tab"; -import { MAX_NAME_LENGTH } from "@bibliothecadao/eternum"; import { useGuilds } from "../../../../hooks/helpers/useGuilds"; -import { hasGuild } from "./utils"; import { GuildMembers } from "./GuildMembers"; +import { hasGuild } from "./utils"; import { Whitelist } from "./Whitelist"; export const MyGuild = () => { @@ -31,7 +31,7 @@ export const MyGuild = () => { const { getAddressGuild } = useGuilds(); - const { userGuildEntityId, isOwner, guildName, memberCount } = getAddressGuild(account.address); + const { userGuildEntityId, isOwner, guildName, memberCount } = getAddressGuild(ContractAddress(account.address)); const [editName, setEditName] = useState(false); const [naming, setNaming] = useState(""); diff --git a/client/src/ui/components/worldmap/guilds/Whitelist.tsx b/client/src/ui/components/worldmap/guilds/Whitelist.tsx index c047cfa9b..6716f7e52 100644 --- a/client/src/ui/components/worldmap/guilds/Whitelist.tsx +++ b/client/src/ui/components/worldmap/guilds/Whitelist.tsx @@ -7,9 +7,10 @@ import { SortButton, SortInterface } from "../../../elements/SortButton"; import { SortPanel } from "../../../elements/SortPanel"; import { GuildWhitelistAndName, useGuilds } from "../../../../hooks/helpers/useGuilds"; +import { ID } from "@bibliothecadao/eternum"; interface WhitelistProps { - guildEntityId: bigint | undefined; + guildEntityId: ID | undefined; isOwner: boolean; } diff --git a/client/src/ui/components/worldmap/guilds/utils.tsx b/client/src/ui/components/worldmap/guilds/utils.tsx index 33e085229..1dc3f6671 100644 --- a/client/src/ui/components/worldmap/guilds/utils.tsx +++ b/client/src/ui/components/worldmap/guilds/utils.tsx @@ -1,5 +1,7 @@ -export const hasGuild = (guildEntityId: bigint | undefined) => { - if (guildEntityId === 0n || guildEntityId === undefined) { +import { ID } from "@bibliothecadao/eternum"; + +export const hasGuild = (guildEntityId: ID | undefined) => { + if (guildEntityId === 0 || guildEntityId === undefined) { return false; } return true; diff --git a/client/src/ui/components/worldmap/hexagon/HexagonGeometry.tsx b/client/src/ui/components/worldmap/hexagon/HexagonGeometry.tsx index 04c5d44fa..7d202e163 100644 --- a/client/src/ui/components/worldmap/hexagon/HexagonGeometry.tsx +++ b/client/src/ui/components/worldmap/hexagon/HexagonGeometry.tsx @@ -35,21 +35,3 @@ export const createHexagonShape = (radius: number) => { return shape; }; - -export const createHexagonPath = (radius: number) => { - const path = new THREE.CurvePath(); - const points = []; - for (let i = 0; i <= 6; i++) { - // Loop one more time to close the hexagon - const angle = (Math.PI / 3) * i - Math.PI / 2; - const x = radius * Math.cos(angle); - const y = radius * Math.sin(angle); - points.push(new THREE.Vector3(x, 0, y)); // Assuming hexagon lies on XZ plane - } - for (let i = 0; i < points.length - 1; i++) { - const lineCurve = new THREE.LineCurve3(points[i], points[i + 1]); - path.add(lineCurve); - } - - return path; -}; diff --git a/client/src/ui/components/worldmap/hexagon/useEventHandlers.tsx b/client/src/ui/components/worldmap/hexagon/useEventHandlers.tsx index f97963680..6849e3b2c 100644 --- a/client/src/ui/components/worldmap/hexagon/useEventHandlers.tsx +++ b/client/src/ui/components/worldmap/hexagon/useEventHandlers.tsx @@ -4,10 +4,10 @@ import { useCallback, useEffect, useRef } from "react"; import * as THREE from "three"; import { useExplore } from "../../../../hooks/helpers/useExplore"; import { useTravel } from "../../../../hooks/helpers/useTravel"; -import { useNotificationsStore } from "../../../../hooks/store/useNotificationsStore"; import useUIStore from "../../../../hooks/store/useUIStore"; import { findDirection, getColRowFromUIPosition } from "../../../utils/utils"; import { getPositionsAtIndex } from "./utils"; +import { ID } from "@bibliothecadao/eternum"; export const useEventHandlers = (explored: Map>) => { const currentArmiesTick = useBlockchainStore((state) => state.currentArmiesTick); @@ -25,8 +25,6 @@ export const useEventHandlers = (explored: Map>) => { const clearSelection = useUIStore((state) => state.clearSelection); const setView = useUIStore((state) => state.setLeftNavigationView); - const setExploreNotification = useNotificationsStore((state) => state.setExploreNotification); - // refs const selectedEntityRef = useRef(selectedEntity); const hoveredHexRef = useRef(hoveredHex); @@ -97,7 +95,7 @@ export const useEventHandlers = (explored: Map>) => { } }; - const handleArmyActionClick = (id: bigint) => { + const handleArmyActionClick = (id: ID) => { if (e.button === 2) return; if (!hoveredHexRef.current) return; const travelPath = travelPathsRef.current.get(`${hoveredHexRef.current.col},${hoveredHexRef.current.row}`); @@ -124,7 +122,7 @@ export const useEventHandlers = (explored: Map>) => { path, currentArmiesTick, }: { - id: bigint; + id: ID; path: any[]; currentArmiesTick: number; }) { @@ -143,7 +141,7 @@ export const useEventHandlers = (explored: Map>) => { path, currentArmiesTick, }: { - id: bigint; + id: ID; path: any[]; currentArmiesTick: number; }) { @@ -152,12 +150,6 @@ export const useEventHandlers = (explored: Map>) => { path.length === 2 ? findDirection({ col: path[0].x, row: path[0].y }, { col: path[1].x, row: path[1].y }) : undefined; - const hexIndex = hexData.findIndex((h) => h.col === path[1].x && h.row === path[1].y); - const biome = hexData[hexIndex].biome; - setExploreNotification({ - entityId: id, - biome, - }); clearSelection(); diff --git a/client/src/ui/components/worldmap/hexagon/useTravelPath.tsx b/client/src/ui/components/worldmap/hexagon/useTravelPath.tsx index df282f2be..c4dcbb36c 100644 --- a/client/src/ui/components/worldmap/hexagon/useTravelPath.tsx +++ b/client/src/ui/components/worldmap/hexagon/useTravelPath.tsx @@ -20,14 +20,14 @@ export const useTravelPath = () => { const { useStaminaByEntityId } = useStamina(); const { getEntityOwner } = useRealm(); - const stamina = useStaminaByEntityId({ travelingEntityId: selectedEntity?.id || 0n }); + const stamina = useStaminaByEntityId({ travelingEntityId: selectedEntity?.id || 0 }); useEffect(() => { if (!selectedEntity || !stamina) return; const maxTravelPossible = Math.floor((stamina.amount || 0) / EternumGlobalConfig.stamina.travelCost); const entityOwner = getEntityOwner(selectedEntity.id); - const food = getFoodResources(entityOwner || 0n); + const food = getFoodResources(entityOwner || 0); const pathMap = findAccessiblePositionsAndPaths( selectedEntity.position, diff --git a/client/src/ui/components/worldmap/hexagon/utils.tsx b/client/src/ui/components/worldmap/hexagon/utils.tsx index dfa4262c0..1caf44012 100644 --- a/client/src/ui/components/worldmap/hexagon/utils.tsx +++ b/client/src/ui/components/worldmap/hexagon/utils.tsx @@ -1,4 +1,3 @@ -import { Color } from "three"; import { EternumGlobalConfig, Position, @@ -6,8 +5,6 @@ import { ResourcesIds, TROOPS_STAMINAS, getNeighborHexes, - neighborOffsetsEven, - neighborOffsetsOdd, } from "@bibliothecadao/eternum"; const matrix = new Matrix4(); @@ -15,22 +12,6 @@ const positions = new Vector3(); import { InstancedMesh, Matrix4, Vector3 } from "three"; import { FELT_CENTER } from "@/ui/config"; -export const isNeighbor = (pos1: Position, pos2: Position) => { - const neighborOffsets = pos1.y % 2 === 0 ? neighborOffsetsEven : neighborOffsetsOdd; - for (const { i, j } of neighborOffsets) { - if (pos1.x + i === pos2.x && pos1.y + j === pos2.y) { - return true; - } - } - return false; -}; - -export const getGrayscaleColor = (color: Color) => { - const luminance = 0.299 * color.r + 0.587 * color.g + 0.114 * color.b; - const darkerLuminance = luminance * 0.5; // Make the grayscale color darker, closer to black - return darkerLuminance; -}; - export const getPositionsAtIndex = (mesh: InstancedMesh, index: number) => { if (!mesh || !mesh.isInstancedMesh) { console.error("The provided mesh is not an InstancedMesh."); diff --git a/client/src/ui/components/worldmap/leaderboard/LeaderboardPanel.tsx b/client/src/ui/components/worldmap/leaderboard/LeaderboardPanel.tsx index d49bed0f8..2043f92eb 100644 --- a/client/src/ui/components/worldmap/leaderboard/LeaderboardPanel.tsx +++ b/client/src/ui/components/worldmap/leaderboard/LeaderboardPanel.tsx @@ -25,15 +25,6 @@ export const LeaderboardPanel = () => { ), component: , }, - // { - // key: "leaderboard", - // label: ( - //
- //
Orders
- //
- // ), - // component: , - // }, ], [selectedTab], ); diff --git a/client/src/ui/components/worldmap/leaderboard/PlayersLeaderboard.tsx b/client/src/ui/components/worldmap/leaderboard/PlayersLeaderboard.tsx index e9cb6de89..9e9fc94b7 100644 --- a/client/src/ui/components/worldmap/leaderboard/PlayersLeaderboard.tsx +++ b/client/src/ui/components/worldmap/leaderboard/PlayersLeaderboard.tsx @@ -67,7 +67,7 @@ export const PlayersLeaderboard = () => {
{`#${rank}`}
{addressName}
-
{displayAddress(address)}
+
{displayAddress(address.toString(16))}
{currencyIntlFormat(totalPoints, 0)}
); diff --git a/client/src/ui/components/worldmap/realms/RealmListItem.tsx b/client/src/ui/components/worldmap/realms/RealmListItem.tsx deleted file mode 100644 index 81d46284b..000000000 --- a/client/src/ui/components/worldmap/realms/RealmListItem.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { Realm } from "@/hooks/helpers/useStructures"; -import { Headline } from "@/ui/elements/Headline"; -import { findResourceById, orderNameDict } from "@bibliothecadao/eternum"; -import clsx from "clsx"; -import { RealmExtended } from "../../../../hooks/helpers/useRealm"; -import { OrderIcon } from "../../../elements/OrderIcon"; -import { ResourceIcon } from "../../../elements/ResourceIcon"; -import { InventoryResources } from "../../resources/InventoryResources"; - -type RealmListItemProps = { - realm: Realm | RealmExtended; - extraButton?: JSX.Element; -}; - -export const RealmListItem = ({ realm, extraButton }: RealmListItemProps) => { - return ( -
-
- {realm && ( -
- -
- {realm.order && } -
{realm.name}
-
-
-
- )} -
-
-
-
-
Produces
- {realm.resources && - realm.resources.map((resourceId: number) => ( -
- -
- ))} -
-
-
-
Inventory
- - {extraButton || ""} -
- ); -}; diff --git a/client/src/ui/components/worldmap/realms/RealmsListComponent.tsx b/client/src/ui/components/worldmap/realms/RealmsListComponent.tsx deleted file mode 100644 index 86838b776..000000000 --- a/client/src/ui/components/worldmap/realms/RealmsListComponent.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import { useMemo } from "react"; -import { RealmListItem } from "./RealmListItem"; -import { useGetRealms } from "../../../../hooks/helpers/useRealm"; -import useRealmStore from "../../../../hooks/store/useRealmStore"; -import ListSelect from "@/ui/elements/ListSelect"; - -import { - Select, - SelectContent, - SelectGroup, - SelectItem, - SelectLabel, - SelectTrigger, - SelectValue, -} from "@/ui/elements/Select"; - -type RealmsListComponentProps = { - onlyMyRealms?: boolean; -}; - -export const RealmsListComponent = ({ onlyMyRealms = false }: RealmsListComponentProps) => { - const realms = useGetRealms(); - - const realmEntityIds = useRealmStore((state) => state.realmEntityIds); - const myRealms = onlyMyRealms ? realmEntityIds.map((realm) => realm.realmEntityId) : []; - - const realmsList = useMemo(() => { - if (onlyMyRealms) { - return realms.filter((realm) => myRealms.includes(realm.entity_id)); - } else { - return realms; - } - }, [realms, myRealms]); - - return ( - <> -
- {realmsList.map((realm) => { - return ; - })} -
- - ); -}; - -export const RealmSelect = ({ onlyMyRealms = false }: RealmsListComponentProps) => { - const realms = useGetRealms(); - - const realmEntityIds = useRealmStore((state) => state.realmEntityIds); - const myRealms = onlyMyRealms ? realmEntityIds.map((realm) => realm.realmEntityId) : []; - - const realmsList = useMemo(() => { - if (onlyMyRealms) { - return realms.filter((realm) => myRealms.includes(realm.entity_id)); - } else { - return realms; - } - }, [realms, myRealms]); - - return ( - - ); -}; diff --git a/client/src/ui/components/worldmap/realms/RealmsPositions.tsx b/client/src/ui/components/worldmap/realms/RealmsPositions.tsx deleted file mode 100644 index 1289cce4e..000000000 --- a/client/src/ui/components/worldmap/realms/RealmsPositions.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import * as THREE from "three"; -import { useState, useEffect, useMemo } from "react"; -import { useControls } from "leva"; -import realmsJson from "../../../../data/geodata/realms.json"; -import useUIStore from "../../../../hooks/store/useUIStore"; - -const RealmsPositions = () => { - const [bufferGeometry, setBufferGeometry] = useState(new THREE.BufferGeometry()); - - const setCameraPosition = useUIStore((state) => state.setCameraPosition); - const setCameraTarget = useUIStore((state) => state.setCameraTarget); - - const { realmsPosition, realmsScale } = useControls({ - realmsPosition: { - value: { x: 0, z: 0, y: 0.65 }, - step: 0.01, - }, - realmsScale: { - value: 1, - step: 0.01, - }, - }); - - const calculatedPositions = useMemo(() => { - const tmpPos = new Float32Array(realmsJson.features.length * 3); - for (let i = 0; i < realmsJson.features.length; i++) { - const i3 = i * 3; - // realms.xy[0], realms.xy[1], 3 - tmpPos[i3] = realmsJson.features[i].xy[0]; - tmpPos[i3 + 1] = realmsJson.features[i].xy[1]; - tmpPos[i3 + 2] = 0.233; - } - return tmpPos; - }, []); - - const calculatedColors = useMemo(() => { - const tmpCol = new Float32Array(realmsJson.features.length * 3); - for (let i = 0; i < realmsJson.features.length; i++) { - const i3 = i * 3; - // realms.xy[0], realms.xy[1], 3 - tmpCol[i3] = 1; - tmpCol[i3 + 1] = 0; - tmpCol[i3 + 2] = 0; - } - return tmpCol; - }, []); - - useEffect(() => { - bufferGeometry.setAttribute("position", new THREE.BufferAttribute(calculatedPositions, 3)); - - bufferGeometry.setAttribute("color", new THREE.BufferAttribute(calculatedColors, 3)); - }, []); - - const realmsMaterial = new THREE.PointsMaterial({ - size: 1, - depthWrite: false, - vertexColors: true, - }); - const clickHandler = (e: any) => { - const colors = calculatedColors; - const positions = calculatedPositions; - for (let inter of e.intersections) { - // recolor clicked and +- 100 around - const i3 = inter.index * 3; - // realms.xy[0], realms.xy[1], 3 - colors[i3] = 1; - colors[i3 + 1] = 1; - colors[i3 + 2] = 0; - } - const point = e.intersections[0].point; - const newGeometry = new THREE.BufferGeometry(); - newGeometry.setAttribute("position", new THREE.BufferAttribute(positions, 3)); - newGeometry.setAttribute("color", new THREE.BufferAttribute(colors, 3)); - setBufferGeometry(newGeometry); - setCameraTarget(new THREE.Vector3(point.x, point.y, point.z)); - setCameraPosition( - new THREE.Vector3(point.x + (50 * Math.random() < 1 ? 1 : -1), 35, point.z + 50 * Math.random() < 1 ? 1 : -1), - ); - }; - - return ( - <> - - - ); -}; - -export default RealmsPositions; diff --git a/client/src/ui/components/worldmap/structures/StructureListItem.tsx b/client/src/ui/components/worldmap/structures/StructureListItem.tsx index c8df3e18c..e9ff6b976 100644 --- a/client/src/ui/components/worldmap/structures/StructureListItem.tsx +++ b/client/src/ui/components/worldmap/structures/StructureListItem.tsx @@ -30,16 +30,16 @@ export const StructureListItem = ({ structure, setShowMergeTroopsPopup, ownArmyS const setBattleView = useUIStore((state) => state.setBattleView); const { getRealmAddressName } = useRealm(); - const addressName = getRealmAddressName(BigInt(structure.entity_id)); + const addressName = getRealmAddressName(structure.entity_id); const { getHyperstructureProgress } = useHyperstructures(); const progress = structure.category === StructureType[StructureType.Hyperstructure] - ? getHyperstructureProgress(BigInt(structure.entity_id)) + ? getHyperstructureProgress(structure.entity_id) : undefined; - const battleManager = useMemo(() => new BattleManager(structure.protector?.battle_id || 0n, dojo), [structure]); + const battleManager = useMemo(() => new BattleManager(structure.protector?.battle_id || 0, dojo), [structure]); const { updatedBattle } = useMemo(() => { if (!currentTimestamp) throw new Error("Current timestamp is undefined"); @@ -47,7 +47,7 @@ export const StructureListItem = ({ structure, setShowMergeTroopsPopup, ownArmyS return { updatedBattle }; }, [currentTimestamp]); - const userArmyInBattle = getUserArmyInBattle(updatedBattle?.entity_id || 0n); + const userArmyInBattle = getUserArmyInBattle(updatedBattle?.entity_id || 0); const battleButtons = useMemo(() => { if (!currentTimestamp) throw new Error("Current timestamp is undefined"); @@ -58,7 +58,7 @@ export const StructureListItem = ({ structure, setShowMergeTroopsPopup, ownArmyS className="fill-gold h-6 w-6 my-auto animate-slow transition-all hover:fill-gold/50 hover:scale-125" onClick={() => setBattleView({ - battle: updatedBattle!.entity_id, + battleEntityId: updatedBattle!.entity_id, targetArmy: undefined, ownArmyEntityId: undefined, }) @@ -80,7 +80,7 @@ export const StructureListItem = ({ structure, setShowMergeTroopsPopup, ownArmyS className="fill-gold h-6 w-6 my-auto animate-slow transition-all hover:fill-gold/50 hover:scale-125" onClick={() => setBattleView({ - battle: updatedBattle?.entity_id, + battleEntityId: updatedBattle?.entity_id, targetArmy: structure.protector?.entity_id, ownArmyEntityId: ownArmySelected?.entity_id, }) @@ -109,7 +109,7 @@ export const StructureListItem = ({ structure, setShowMergeTroopsPopup, ownArmyS onClick={() => setBattleView({ engage: true, - battle: undefined, + battleEntityId: undefined, ownArmyEntityId: ownArmySelected?.entity_id, targetArmy: structure.protector?.entity_id, }) diff --git a/client/src/ui/config.tsx b/client/src/ui/config.tsx index 1b4e10243..cc045d67a 100644 --- a/client/src/ui/config.tsx +++ b/client/src/ui/config.tsx @@ -7,17 +7,16 @@ export const COLS = 500; export const FELT_CENTER = 2147483647; export const EXPLORE_COLOUR = 0x2563eb; export const TRAVEL_COLOUR = 0xffce31; -export const CLICKED_HEX_COLOR = 0xff5733; export const ACCESSIBLE_POSITIONS_COLOUR = 0xffffff; -export enum ResourceMiningTypes { +enum ResourceMiningTypes { Forge = "forge", Mine = "mine", LumberMill = "lumber_mill", Dragonhide = "dragonhide", } -export const BUILD_IMAGES_PREFIX = "/images/buildings/construction/"; +const BUILD_IMAGES_PREFIX = "/images/buildings/construction/"; export const BUILDING_IMAGES_PATH = { [BuildingType.Castle]: "", [BuildingType.Bank]: "", diff --git a/client/src/ui/containers/BlurOverlayContainer.tsx b/client/src/ui/containers/BlurOverlayContainer.tsx deleted file mode 100644 index a4675d7a1..000000000 --- a/client/src/ui/containers/BlurOverlayContainer.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { Transition } from "@headlessui/react"; -import React, { Fragment } from "react"; -import useUIStore from "../../hooks/store/useUIStore"; - -type BlurOverlayContainerProps = { - children?: React.ReactNode; -} & React.HTMLAttributes; - -export const BlurOverlayContainer = ({ children }: BlurOverlayContainerProps) => { - const showBlurOverlay = useUIStore((state) => state.showBlurOverlay); - return ( - -
- {children} -
-
- ); -}; diff --git a/client/src/ui/containers/BottomLeftContainer.tsx b/client/src/ui/containers/BottomLeftContainer.tsx deleted file mode 100644 index 6d2a6873c..000000000 --- a/client/src/ui/containers/BottomLeftContainer.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { ReactNode } from "react"; - -export const BottomLeftContainer = ({ children }: { children?: ReactNode }) => { - return
{children}
; -}; diff --git a/client/src/ui/containers/ContentContainer.tsx b/client/src/ui/containers/ContentContainer.tsx deleted file mode 100644 index 722e5ae61..000000000 --- a/client/src/ui/containers/ContentContainer.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { Transition } from "@headlessui/react"; -import useUIStore from "../../hooks/store/useUIStore"; -import { Fragment } from "react"; - -const ContentContainer = ({ children }: { children: React.ReactNode }) => { - const isSideMenuOpened = useUIStore((state) => state.isSideMenuOpened); - - return ( - -
{children}
-
- ); -}; - -export default ContentContainer; diff --git a/client/src/ui/containers/LeftMiddleContainer.tsx b/client/src/ui/containers/LeftMiddleContainer.tsx index 84dadeca4..6a5b16e86 100644 --- a/client/src/ui/containers/LeftMiddleContainer.tsx +++ b/client/src/ui/containers/LeftMiddleContainer.tsx @@ -1,4 +1,4 @@ -export const LeftMiddleContainer = ({ children }: { children: React.ReactNode }) => { +const LeftMiddleContainer = ({ children }: { children: React.ReactNode }) => { return
{children}
; }; diff --git a/client/src/ui/containers/RightMiddleContainer.tsx b/client/src/ui/containers/RightMiddleContainer.tsx index 6f8331fdb..77db6dd35 100644 --- a/client/src/ui/containers/RightMiddleContainer.tsx +++ b/client/src/ui/containers/RightMiddleContainer.tsx @@ -1,4 +1,4 @@ -export const RightMiddleContainer = ({ children }: { children: React.ReactNode }) => { +const RightMiddleContainer = ({ children }: { children: React.ReactNode }) => { return
{children}
; }; diff --git a/client/src/ui/containers/SecondaryContainer.tsx b/client/src/ui/containers/SecondaryContainer.tsx deleted file mode 100644 index b9db4e58a..000000000 --- a/client/src/ui/containers/SecondaryContainer.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { ReactNode } from "react"; -import clsx from "clsx"; - -interface SecondaryContainerProps { - children?: ReactNode; - className?: string; -} - -export const SecondaryContainer = ({ children, className }: SecondaryContainerProps) => { - return ( -
- {children} -
- ); -}; diff --git a/client/src/ui/containers/TopContainer.tsx b/client/src/ui/containers/TopContainer.tsx deleted file mode 100644 index f457848ff..000000000 --- a/client/src/ui/containers/TopContainer.tsx +++ /dev/null @@ -1,5 +0,0 @@ -export const TopContainer = ({ children }: { children: React.ReactNode }) => { - return
{children}
; -}; - -export default TopContainer; diff --git a/client/src/ui/containers/TopLeftContainer.tsx b/client/src/ui/containers/TopLeftContainer.tsx index bc0e53ecc..55b8753f3 100644 --- a/client/src/ui/containers/TopLeftContainer.tsx +++ b/client/src/ui/containers/TopLeftContainer.tsx @@ -1,4 +1,4 @@ -export const TopLeftContainer = ({ children }: { children: React.ReactNode }) => { +const TopLeftContainer = ({ children }: { children: React.ReactNode }) => { return
{children}
; }; diff --git a/client/src/ui/containers/TopMiddleContainer.tsx b/client/src/ui/containers/TopMiddleContainer.tsx index 7ff8336e0..138a6c1b7 100644 --- a/client/src/ui/containers/TopMiddleContainer.tsx +++ b/client/src/ui/containers/TopMiddleContainer.tsx @@ -1,4 +1,4 @@ -export const TopContainer = ({ children }: { children: React.ReactNode }) => { +const TopContainer = ({ children }: { children: React.ReactNode }) => { return
{children}
; }; diff --git a/client/src/ui/elements/ActiveLink.tsx b/client/src/ui/elements/ActiveLink.tsx deleted file mode 100644 index c74121bcf..000000000 --- a/client/src/ui/elements/ActiveLink.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { Link, useRoute } from "wouter"; - -const ActiveLink = (props: any) => { - const [isActive] = useRoute(props.href); - return ( - - {props.children} - - ); -}; - -export default ActiveLink; diff --git a/client/src/ui/elements/Badge.tsx b/client/src/ui/elements/Badge.tsx deleted file mode 100644 index 9365dae11..000000000 --- a/client/src/ui/elements/Badge.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import clsx from "clsx"; -import React, { ComponentPropsWithRef } from "react"; - -type BadgeProps = { - children?: React.ReactNode; - size: "sm" | "md" | "lg" | "xl"; - type?: "danger" | "success" | "primary"; - bordered?: boolean; -} & ComponentPropsWithRef<"div">; - -const sizes = { - sm: "min-w-[0.5rem] h-2 p-1", - md: "min-w-[1rem] h-4 p-1", - lg: "min-w-[1.25rem] h-5 p-2", - xl: "min-w-[1.5rem] h-6 p-2", -}; - -const STYLES = { - base: "flex items-center justify-center rounded-full text-black", - bordered: "border-2 border-black", - danger: "bg-order-giants !text-white", - success: "bg-order-brilliance", - primary: "bg-gold", -}; -export const Badge = ({ children, size, className, type = "primary", bordered }: BadgeProps) => ( -
{children}
-); diff --git a/client/src/ui/elements/BaseStatus.tsx b/client/src/ui/elements/BaseStatus.tsx deleted file mode 100644 index 94b6e8d15..000000000 --- a/client/src/ui/elements/BaseStatus.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import React, { useEffect } from "react"; - -type BaseStatusProps = { - state: "bad" | "neutral" | "good"; - children?: React.ReactNode; -}; - -const STYLES = { - base: "flex items-center justify-center ml-auto text-xs rounded-full cursor-default h-7", - bad: " text-anger-light", - neutral: "text-gold", - good: "text-order-vitriol", -}; -export const BaseStatus = ({ state, children }: BaseStatusProps) => { - useEffect(() => {}, []); - - return
{children}
; -}; diff --git a/client/src/ui/elements/BaseThreeTooltip.tsx b/client/src/ui/elements/BaseThreeTooltip.tsx index 9485fd2f0..049509b58 100644 --- a/client/src/ui/elements/BaseThreeTooltip.tsx +++ b/client/src/ui/elements/BaseThreeTooltip.tsx @@ -14,9 +14,6 @@ export enum Position { CENTER = "-left-1/2 -mt-[150px]", TOP_CENTER = "-left-1/2 -mt-[300px]", BOTTOM_RIGHT = "rounded-bl-xl rounded-br-xl rounded-tr-xl -left-1", - TOP_RIGHT = "rounded-tl-xl rounded-br-xl rounded-tr-xl -left-1 -mt-[300px]", - TOP_LEFT = "rounded-tl-xl rounded-bl-xl rounded-tr-xl right-[220px] -mt-[280px]", - BOTTOM_LEFT = "rounded-tl-xl rounded-bl-xl rounded-br-xl right-[220px]", } export const BaseThreeTooltip = ({ diff --git a/client/src/ui/elements/BlurryLoadingImage.tsx b/client/src/ui/elements/BlurryLoadingImage.tsx deleted file mode 100644 index af418a1b8..000000000 --- a/client/src/ui/elements/BlurryLoadingImage.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { useEffect, useState } from "react"; -import { Blurhash } from "react-blurhash"; - -export type BlurryLoadingImageProps = { - src: string; - blurhash: string; - height?: string; - width?: string; - imageStyleClass?: string; - divStyleClass?: string; - bgColor?: string; -}; - -const BlurryLoadingImage = ({ - src, - blurhash, - height, - width, - imageStyleClass = "", - divStyleClass = "", - bgColor = "transparent", -}: BlurryLoadingImageProps) => { - const [currentImage, setCurrentImage] = useState(null); - const [loading, setLoading] = useState(true); - - const fetchImage = (src: string) => { - const loadingImage = new Image(); - loadingImage.src = src; - loadingImage.onload = () => { - setCurrentImage(src); - setLoading(false); - }; - }; - - useEffect(() => { - fetchImage(src); - }, [src]); // Add src as a dependency to re-run effect if src changes - - return ( -
- {loading || !currentImage ? ( - - ) : ( - - )} -
- ); -}; - -export default BlurryLoadingImage; diff --git a/client/src/ui/elements/BuildingsCount.tsx b/client/src/ui/elements/BuildingsCount.tsx deleted file mode 100644 index 352a40805..000000000 --- a/client/src/ui/elements/BuildingsCount.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import clsx from "clsx"; -import React from "react"; - -type BuildingsCountProps = { - count: number; - maxCount: number; -} & React.HTMLAttributes; - -export const BuildingsCount = ({ count, maxCount, className }: BuildingsCountProps) => ( -
- {Array(maxCount) - .fill(0) - .map((_, i) => ( -
- ))} -
-); diff --git a/client/src/ui/elements/ChatMessage.tsx b/client/src/ui/elements/ChatMessage.tsx deleted file mode 100644 index c83f8b731..000000000 --- a/client/src/ui/elements/ChatMessage.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import Avatar from "./Avatar"; -// import { OrderIcon } from "./OrderIcon"; -// import { useDojo } from "../DojoContext"; - -export interface ChatMessageProps { - sender: string; - message: string; - avatar: string; - timestamp: string; -} - -const ChatMessage = (props: ChatMessageProps) => { - const { sender, message, avatar, timestamp } = props; - - // const name = useMemo(() => - // (sender.includes('stark') ? - //
- // {sender.split('.')[0]} - // .{sender.split('.')[1]} - //
: {sender}) - // , [sender]); - - return ( -
-
- -
-
-
-
{sender}
- {/* */} -
-
{timestamp}
-
-
{message}
-
-
-
- ); -}; - -export default ChatMessage; diff --git a/client/src/ui/elements/Dot.tsx b/client/src/ui/elements/Dot.tsx deleted file mode 100644 index b5cb4f859..000000000 --- a/client/src/ui/elements/Dot.tsx +++ /dev/null @@ -1,5 +0,0 @@ -type DotProps = { - colorClass: string; -}; - -export const Dot = ({ colorClass }: DotProps) =>
; diff --git a/client/src/ui/elements/FilterButton.tsx b/client/src/ui/elements/FilterButton.tsx deleted file mode 100644 index ce6868f89..000000000 --- a/client/src/ui/elements/FilterButton.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import clsx from "clsx"; -import React, { ComponentPropsWithRef } from "react"; -import { ReactComponent as Cross } from "@/assets/icons/common/cross-circle.svg"; -import { ReactComponent as CaretDownFill } from "@/assets/icons/common/caret-down-fill.svg"; - -type FilterButtonProps = { - active: boolean; - children?: React.ReactNode; -} & ComponentPropsWithRef<"button">; - -export const FilterButton = ({ active, children, onClick }: FilterButtonProps) => { - return ( - - ); -}; diff --git a/client/src/ui/elements/FiltersPanel.tsx b/client/src/ui/elements/FiltersPanel.tsx deleted file mode 100644 index e1d220b3e..000000000 --- a/client/src/ui/elements/FiltersPanel.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import clsx from "clsx"; -import React from "react"; - -type FiltersPanelProps = { - children?: React.ReactNode; -} & React.ComponentPropsWithRef<"div">; - -export const FiltersPanel = ({ children, className }: FiltersPanelProps) => { - return
{children}
; -}; diff --git a/client/src/ui/elements/ListSelect.tsx b/client/src/ui/elements/ListSelect.tsx index 0a3436c0a..cfc94b311 100644 --- a/client/src/ui/elements/ListSelect.tsx +++ b/client/src/ui/elements/ListSelect.tsx @@ -4,7 +4,7 @@ import { Listbox, Transition } from "@headlessui/react"; import clsx from "clsx"; import { Fragment, ReactNode, useMemo } from "react"; -export interface ListSelectOption { +interface ListSelectOption { id: any; label: ReactNode; } diff --git a/client/src/ui/elements/MusicPlayer.tsx b/client/src/ui/elements/MusicPlayer.tsx deleted file mode 100644 index 7002a483f..000000000 --- a/client/src/ui/elements/MusicPlayer.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { useState } from "react"; -import Button from "./Button"; -import { useMusicPlayer } from "../../hooks/useMusic"; - -export const MusicPlayer = () => { - const { play, next, trackName, isPlaying, stop } = useMusicPlayer(); - - const [loaded, setLoaded] = useState(false); - - const handlePlay = () => { - if (isPlaying) { - stop(); - } else { - play(); - } - }; - - return ( - <> - {!loaded &&
setLoaded(true)} className="h-full w-full absolute backdrop-blur-sm">
} - -
- - -
- {trackName}
Casey Wescott
{" "} -
- - -
- - ); -}; diff --git a/client/src/ui/elements/OnlineStatus.tsx b/client/src/ui/elements/OnlineStatus.tsx deleted file mode 100644 index f327b6f8e..000000000 --- a/client/src/ui/elements/OnlineStatus.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import clsx from "clsx"; -import React from "react"; - -type OnlineStatusProps = { - status: "online" | "recently" | "offline"; -} & React.HTMLAttributes; - -const COLORS = { - online: "bg-order-brilliance", - recently: "bg-gold", - offline: "bg-danger", -}; -export const OnlineStatus = ({ status, className, ...props }: OnlineStatusProps) => ( -
-); diff --git a/client/src/ui/elements/OrderIcon.tsx b/client/src/ui/elements/OrderIcon.tsx index 1d4b6064e..a549a7f2c 100644 --- a/client/src/ui/elements/OrderIcon.tsx +++ b/client/src/ui/elements/OrderIcon.tsx @@ -19,7 +19,7 @@ import { ReactComponent as Gods } from "@/assets/icons/orders/gods.svg"; import useUIStore from "../../hooks/store/useUIStore"; import { orders } from "@bibliothecadao/eternum"; -export type Props = { +type Props = { order: string; size: keyof (typeof STYLES)["size"]; className?: string; diff --git a/client/src/ui/elements/PercentageSelection.tsx b/client/src/ui/elements/PercentageSelection.tsx deleted file mode 100644 index c261c0c7b..000000000 --- a/client/src/ui/elements/PercentageSelection.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import clsx from "clsx"; -import Button from "./Button"; - -type PercentageSelectionProps = { - className?: string; - percentages: number[]; - setPercentage: (percentage: number) => void; -}; - -export const PercentageSelection = ({ className = "", percentages, setPercentage }: PercentageSelectionProps) => { - return ( -
- {percentages.map((percentage, i) => ( - - ))} -
- ); -}; diff --git a/client/src/ui/elements/ProgressBar.tsx b/client/src/ui/elements/ProgressBar.tsx deleted file mode 100644 index f9193a6ad..000000000 --- a/client/src/ui/elements/ProgressBar.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import clsx from "clsx"; - -interface ProgressBarProps { - progress: number; - children?: React.ReactNode; - className?: string; - containerClassName?: string; - rounded?: boolean; -} -const ProgressBar = ({ progress, children, className, rounded, containerClassName }: ProgressBarProps) => { - return ( -
-
- {children} -
-
- ); -}; - -export default ProgressBar; diff --git a/client/src/ui/elements/RealmBadge.tsx b/client/src/ui/elements/RealmBadge.tsx deleted file mode 100644 index 2b1499ee0..000000000 --- a/client/src/ui/elements/RealmBadge.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { ComponentPropsWithRef, useState } from "react"; -import { OrderIcon } from "./OrderIcon"; -import clsx from "clsx"; - -type RealmBadgeProps = { - active?: boolean; - realm: { - id: bigint; - name: string; - order: string; - }; -} & ComponentPropsWithRef<"div">; - -export const RealmBadge = ({ active, realm, className, ...props }: RealmBadgeProps) => { - const [hovered, setHovered] = useState(false); - - const hoveredOrActive = hovered || active; - - const firstLetter = realm.name[0]; - const otherLetters = realm.name.slice(1); - - return ( -
setHovered(true)} - onMouseLeave={() => setHovered(false)} - className={clsx( - "flex h-12 px-4 w-auto transition-all duration-200 items-center overflow-hidden text-white border rounded-[10px] cursor-pointer bg-brown whitespace-nowrap", - hoveredOrActive ? "max-w-[150px] border-white text-white" : "max-w-[40px]", - active && `bg-order-${realm.order}`, - className, - )} - {...props} - > - - {firstLetter} - - {otherLetters} - -
- ); -}; diff --git a/client/src/ui/elements/ResourceIcon.tsx b/client/src/ui/elements/ResourceIcon.tsx index 6aefb8056..8e34bb830 100644 --- a/client/src/ui/elements/ResourceIcon.tsx +++ b/client/src/ui/elements/ResourceIcon.tsx @@ -8,7 +8,7 @@ import { ReactComponent as Spores } from "@/assets/icons/resources/Spores.svg"; import clsx from "clsx"; import type { ReactElement } from "react"; -export type Props = { +type Props = { isLabor?: boolean; resource: string; size: keyof (typeof STYLES)["size"]; diff --git a/client/src/ui/elements/Select.tsx b/client/src/ui/elements/Select.tsx index 4d4eb7574..cee800aca 100644 --- a/client/src/ui/elements/Select.tsx +++ b/client/src/ui/elements/Select.tsx @@ -130,12 +130,14 @@ SelectSeparator.displayName = SelectPrimitive.Separator.displayName; export { Select, SelectContent, - SelectGroup, SelectItem, - SelectLabel, - SelectScrollDownButton, - SelectScrollUpButton, - SelectSeparator, SelectTrigger, SelectValue, + + //// Raises knip issues, if needed uncomment + // SelectGroup, + // SelectLabel, + // SelectScrollDownButton, + // SelectScrollUpButton, + // SelectSeparator, }; diff --git a/client/src/ui/elements/SelectableResource.tsx b/client/src/ui/elements/SelectableResource.tsx deleted file mode 100644 index 4eb71676a..000000000 --- a/client/src/ui/elements/SelectableResource.tsx +++ /dev/null @@ -1,157 +0,0 @@ -import React from "react"; -import { ResourcesIds, findResourceById } from "@bibliothecadao/eternum"; -import clsx from "clsx"; -import { ResourceIcon } from "./ResourceIcon"; -import { soundSelector, useUiSounds } from "../../hooks/useUISound"; -import { currencyFormat } from "../utils/utils"; -import useUIStore from "../../hooks/store/useUIStore"; - -type SelectableResourceProps = { - resourceId: number; - amount?: number; - selected?: boolean; - disabled?: boolean; -} & React.HTMLAttributes; - -export const SelectableResource = ({ resourceId, amount, selected, disabled, onClick }: SelectableResourceProps) => { - const resource = findResourceById(resourceId); - const setTooltip = useUIStore((state) => state.setTooltip); - - const { play: playAddWood } = useUiSounds(soundSelector.addWood); - const { play: playAddStone } = useUiSounds(soundSelector.addStone); - const { play: playAddCoal } = useUiSounds(soundSelector.addCoal); - const { play: playAddCopper } = useUiSounds(soundSelector.addCopper); - const { play: playAddObsidian } = useUiSounds(soundSelector.addObsidian); - const { play: playAddSilver } = useUiSounds(soundSelector.addSilver); - const { play: playAddIronwood } = useUiSounds(soundSelector.addIronwood); - const { play: playAddColdIron } = useUiSounds(soundSelector.addColdIron); - const { play: playAddGold } = useUiSounds(soundSelector.addGold); - const { play: playAddHartwood } = useUiSounds(soundSelector.addHartwood); - const { play: playAddDiamonds } = useUiSounds(soundSelector.addDiamonds); - const { play: playAddSapphire } = useUiSounds(soundSelector.addSapphire); - const { play: playAddRuby } = useUiSounds(soundSelector.addRuby); - const { play: playAddDeepCrystal } = useUiSounds(soundSelector.addDeepCrystal); - const { play: playAddIgnium } = useUiSounds(soundSelector.addIgnium); - const { play: playAddEtherealSilica } = useUiSounds(soundSelector.addEtherealSilica); - - const { play: playAddTrueIce } = useUiSounds(soundSelector.addTrueIce); - const { play: playAddTwilightQuartz } = useUiSounds(soundSelector.addTwilightQuartz); - const { play: playAddAlchemicalSilver } = useUiSounds(soundSelector.addAlchemicalSilver); - const { play: playAddAdamantine } = useUiSounds(soundSelector.addAdamantine); - const { play: playAddMithral } = useUiSounds(soundSelector.addMithral); - const { play: playAddDragonhide } = useUiSounds(soundSelector.addDragonhide); - const { play: playAddWheat } = useUiSounds(soundSelector.addWheat); - const { play: playAddFish } = useUiSounds(soundSelector.addFish); - - const playResourceSound = (resourceId: ResourcesIds) => { - // eslint-disable-next-line sonarjs/no-small-switch - switch (resourceId) { - case ResourcesIds.Wood: - playAddWood(); - break; - case ResourcesIds.Stone: - playAddStone(); - break; - case ResourcesIds.Coal: - playAddCoal(); - break; - case ResourcesIds.Copper: - playAddCopper(); - break; - case ResourcesIds.Obsidian: - playAddObsidian(); - break; - case ResourcesIds.Silver: - playAddSilver(); - break; - case ResourcesIds.Ironwood: - playAddIronwood(); - break; - case ResourcesIds.ColdIron: - playAddColdIron(); - break; - case ResourcesIds.Gold: - playAddGold(); - break; - case ResourcesIds.Hartwood: - playAddHartwood(); - break; - case ResourcesIds.Diamonds: - playAddDiamonds(); - break; - case ResourcesIds.Sapphire: - playAddSapphire(); - break; - case ResourcesIds.Ruby: - playAddRuby(); - break; - case ResourcesIds.DeepCrystal: - playAddDeepCrystal(); - break; - case ResourcesIds.Ignium: - playAddIgnium(); - break; - case ResourcesIds.EtherealSilica: - playAddEtherealSilica(); - break; - case ResourcesIds.TrueIce: - playAddTrueIce(); - break; - case ResourcesIds.TwilightQuartz: - playAddTwilightQuartz(); - break; - case ResourcesIds.AlchemicalSilver: - playAddAlchemicalSilver(); - break; - case ResourcesIds.Adamantine: - playAddAdamantine(); - break; - case ResourcesIds.Mithral: - playAddMithral(); - break; - case ResourcesIds.Dragonhide: - playAddDragonhide(); - break; - case ResourcesIds.Wheat: - playAddWheat(); - break; - case ResourcesIds.Fish: - playAddFish(); - break; - default: - break; - } - }; - - return ( -
- setTooltip({ - position: "bottom", - content: ( - <> -
- {resource?.trait} -
{currencyFormat(amount || 0, 0)}
-
- - ), - }) - } - onMouseLeave={() => setTooltip(null)} - onClick={(e) => { - if (!disabled && onClick) { - onClick(e); - playResourceSound(resourceId); - } - }} - className={clsx( - "p-2 relative cursor-pointer group border border-transparent transition-colors duration-200 rounded-xl bg-black/60 hover:border-lightest", - selected && "!border-gold", - disabled && "opacity-30 cursor-not-allowed pointer-events-none", - )} - > - -
- ); -}; diff --git a/client/src/ui/elements/StaminaResource.tsx b/client/src/ui/elements/StaminaResource.tsx index fddcb5de8..f5f9d84a3 100644 --- a/client/src/ui/elements/StaminaResource.tsx +++ b/client/src/ui/elements/StaminaResource.tsx @@ -1,10 +1,10 @@ import { useStamina } from "@/hooks/helpers/useStamina"; -import { EternumGlobalConfig } from "@bibliothecadao/eternum"; +import { EternumGlobalConfig, ID } from "@bibliothecadao/eternum"; import clsx from "clsx"; -export const StaminaResource = ({ entityId, className }: { entityId: bigint | undefined; className?: string }) => { +export const StaminaResource = ({ entityId, className }: { entityId: ID | undefined; className?: string }) => { const { useStaminaByEntityId, getMaxStaminaByEntityId } = useStamina(); - const stamina = useStaminaByEntityId({ travelingEntityId: entityId || 0n }); + const stamina = useStaminaByEntityId({ travelingEntityId: entityId || 0 }); const staminaColor = (stamina?.amount || 0n) < EternumGlobalConfig.stamina.travelCost ? "text-red/80" : "text-yellow/80"; @@ -13,7 +13,7 @@ export const StaminaResource = ({ entityId, className }: { entityId: bigint | un
- STM : {stamina?.amount || 0} / {getMaxStaminaByEntityId(entityId || 0n)} + STM : {stamina?.amount || 0} / {getMaxStaminaByEntityId(entityId || 0)}
diff --git a/client/src/ui/elements/StaminaResourceCost.tsx b/client/src/ui/elements/StaminaResourceCost.tsx index 03b2cc444..7a1d3a10a 100644 --- a/client/src/ui/elements/StaminaResourceCost.tsx +++ b/client/src/ui/elements/StaminaResourceCost.tsx @@ -1,5 +1,5 @@ import { useStamina } from "@/hooks/helpers/useStamina"; -import { EternumGlobalConfig } from "@bibliothecadao/eternum"; +import { EternumGlobalConfig, ID } from "@bibliothecadao/eternum"; import clsx from "clsx"; import { useMemo } from "react"; @@ -8,12 +8,12 @@ export const StaminaResourceCost = ({ travelLength, isExplored, }: { - travelingEntityId: bigint | undefined; + travelingEntityId: ID | undefined; travelLength: number; isExplored: boolean; }) => { const { useStaminaByEntityId } = useStamina(); - const stamina = useStaminaByEntityId({ travelingEntityId: travelingEntityId || 0n }); + const stamina = useStaminaByEntityId({ travelingEntityId: travelingEntityId || 0 }); const destinationHex = useMemo(() => { if (!stamina) return; diff --git a/client/src/ui/elements/Steps.tsx b/client/src/ui/elements/Steps.tsx deleted file mode 100644 index 11614e7b9..000000000 --- a/client/src/ui/elements/Steps.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import clsx from "clsx"; -import React, { Fragment, useMemo } from "react"; - -type StepsProps = { - step: number; - maxStep: number; -} & React.HTMLAttributes; - -export const Steps = ({ step, maxStep, className }: StepsProps) => { - const _step = useMemo(() => step - 1, [step]); - - return ( -
- {Array.from(Array(maxStep).keys()).map((i, index) => ( - -
- {i < maxStep - 1 && ( -
- )} - - ))} -
- ); -}; diff --git a/client/src/ui/elements/TextArea.tsx b/client/src/ui/elements/TextArea.tsx index a5f7335b4..ae128fd60 100644 --- a/client/src/ui/elements/TextArea.tsx +++ b/client/src/ui/elements/TextArea.tsx @@ -2,7 +2,7 @@ import * as React from "react"; import { cn } from "./lib/utils"; -export interface TextareaProps extends React.TextareaHTMLAttributes {} +interface TextareaProps extends React.TextareaHTMLAttributes {} const Textarea = React.forwardRef(({ className, ...props }, ref) => { return ( diff --git a/client/src/ui/elements/TimeoutImage.tsx b/client/src/ui/elements/TimeoutImage.tsx deleted file mode 100644 index 84657b4cd..000000000 --- a/client/src/ui/elements/TimeoutImage.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import { useEffect, useState } from "react"; - -export type TimeoutImageProps = { - image: string; - alt?: string; - imageStyleClass?: string; - divStyleClass?: string; - bgColor?: string; -}; - -const TimeoutImage = ({ - image, - alt = "", - imageStyleClass = "", - divStyleClass = "", - bgColor = "transparent", -}: TimeoutImageProps) => { - const [currentImage, setCurrentImage] = useState(null); - const [_, setLoading] = useState(true); - - const fetchImage = (src: string) => { - const loadingImage = new Image(); - loadingImage.src = src; - loadingImage.onload = () => { - setTimeout(() => { - setCurrentImage(loadingImage.src); - setLoading(false); - }, 2000); - }; - }; - - useEffect(() => { - fetchImage(image); - }, []); - - return ( -
- {currentImage && ( - {alt} - )} - {!currentImage && ( - {alt} - )} -
- ); -}; - -export default TimeoutImage; diff --git a/client/src/ui/elements/Toggle.tsx b/client/src/ui/elements/Toggle.tsx deleted file mode 100644 index bb6bab7b8..000000000 --- a/client/src/ui/elements/Toggle.tsx +++ /dev/null @@ -1,18 +0,0 @@ -type ToggleProps = { - label: string; - checked: boolean; - children?: React.ReactNode; - onChange: (checked: boolean) => void; -}; - -const Toggle = ({ label, checked, onChange }: ToggleProps) => { - return ( - - ); -}; - -export default Toggle; diff --git a/client/src/ui/elements/tab/tabs.tsx b/client/src/ui/elements/tab/tabs.tsx index a6df9092e..608229021 100644 --- a/client/src/ui/elements/tab/tabs.tsx +++ b/client/src/ui/elements/tab/tabs.tsx @@ -35,7 +35,7 @@ export const VARIANTS: any = { }, }; -export interface TabsProps { +interface TabsProps { children: ReactNode; variant?: keyof typeof VARIANTS; className?: string; diff --git a/client/src/ui/modules/chat/ChatModule.tsx b/client/src/ui/modules/chat/ChatModule.tsx deleted file mode 100644 index bccd109b5..000000000 --- a/client/src/ui/modules/chat/ChatModule.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { ChatProvider } from "@/hooks/context/ChatContext"; -import ChatForm from "@/ui/components/chat/ChatForm"; -import { ChatTabs } from "@/ui/components/chat/ChatTabs"; -import { BaseContainer } from "@/ui/containers/BaseContainer"; - -const ChatModule = () => { - return ( - - - - - - - ); -}; - -export default ChatModule; diff --git a/client/src/ui/modules/construction/Construction.tsx b/client/src/ui/modules/construction/Construction.tsx deleted file mode 100644 index f8e8300d3..000000000 --- a/client/src/ui/modules/construction/Construction.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import useUIStore from "@/hooks/store/useUIStore"; -import { OSWindow } from "@/ui/components/navigation/OSWindow"; -import { construction } from "@/ui/components/navigation/Config"; -import { EntityPopulation } from "@/ui/components/entities/EntityPopulation"; - -export const Construction = ({ entityId }: { entityId: bigint | undefined }) => { - const togglePopup = useUIStore((state) => state.togglePopup); - - const isOpen = useUIStore((state) => state.isPopupOpen(construction)); - - return ( - togglePopup(construction)} show={isOpen} title={construction}> - - - ); -}; diff --git a/client/src/ui/modules/entity-details/EnemyArmies.tsx b/client/src/ui/modules/entity-details/EnemyArmies.tsx index 4536367e0..72f1e177b 100644 --- a/client/src/ui/modules/entity-details/EnemyArmies.tsx +++ b/client/src/ui/modules/entity-details/EnemyArmies.tsx @@ -34,7 +34,7 @@ export const EnemyArmies = ({ onClick={() => setBattleView({ engage: true, - battle: undefined, + battleEntityId: undefined, ownArmyEntityId: ownArmySelected.entity_id, targetArmy: army.entity_id, }) diff --git a/client/src/ui/modules/entity-details/EntityDetails.tsx b/client/src/ui/modules/entity-details/EntityDetails.tsx index a7c407c05..d4a3960ef 100644 --- a/client/src/ui/modules/entity-details/EntityDetails.tsx +++ b/client/src/ui/modules/entity-details/EntityDetails.tsx @@ -5,7 +5,7 @@ import { ArmyChip } from "@/ui/components/military/ArmyChip"; import { HintModalButton } from "@/ui/elements/HintModalButton"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/ui/elements/Select"; import { Tabs } from "@/ui/elements/tab"; -import { Position } from "@bibliothecadao/eternum"; +import { ID, Position } from "@bibliothecadao/eternum"; import { useMemo, useState } from "react"; import { Battles } from "./Battles"; import { Entities } from "./Entities"; @@ -28,8 +28,8 @@ export const EntityDetails = () => { [ownArmiesAtPosition], ); - const [ownArmySelected, setOwnArmySelected] = useState<{ id: bigint; position: Position } | undefined>({ - id: userArmies?.[0]?.entity_id || 0n, + const [ownArmySelected, setOwnArmySelected] = useState<{ id: ID; position: Position } | undefined>({ + id: userArmies?.[0]?.entity_id || 0, position: { x: clickedHex?.contractPos.col || 0, y: clickedHex?.contractPos.row || 0, @@ -96,18 +96,18 @@ export const EntityDetails = () => { ); }; -export const SelectActiveArmy = ({ +const SelectActiveArmy = ({ selectedEntity, setOwnArmySelected, userAttackingArmies, }: { selectedEntity: | { - id: bigint; + id: ID; position: Position; } | undefined; - setOwnArmySelected: (val: any) => void; + setOwnArmySelected: (val: { id: ID; position: Position } | undefined) => void; userAttackingArmies: ArmyInfo[]; }) => { return ( @@ -115,7 +115,7 @@ export const SelectActiveArmy = ({ { - setLocalSelectedUnit(BigInt(a)); + setLocalSelectedUnit(Number(a)); }} > diff --git a/client/src/ui/modules/military/battle-view/BattleDetails.tsx b/client/src/ui/modules/military/battle-view/BattleDetails.tsx index 4770796b3..e9ad7a447 100644 --- a/client/src/ui/modules/military/battle-view/BattleDetails.tsx +++ b/client/src/ui/modules/military/battle-view/BattleDetails.tsx @@ -22,7 +22,7 @@ export const BattleDetails = ({ armies }: { armies: (ArmyInfo | undefined)[] | u {army?.name}
- {army?.entityOwner ? getAddressName(String(army.owner.address)) : "Bandits"} + {army?.entityOwner ? getAddressName(army.owner.address) : "Bandits"}
), diff --git a/client/src/ui/modules/military/battle-view/BattleSideView.tsx b/client/src/ui/modules/military/battle-view/BattleSideView.tsx index b43d8b434..80acb6463 100644 --- a/client/src/ui/modules/military/battle-view/BattleSideView.tsx +++ b/client/src/ui/modules/military/battle-view/BattleSideView.tsx @@ -3,7 +3,7 @@ import { useDojo } from "@/hooks/context/DojoContext"; import { ArmyInfo, useArmyByArmyEntityId } from "@/hooks/helpers/useArmies"; import { Structure } from "@/hooks/helpers/useStructures"; import Button from "@/ui/elements/Button"; -import { BattleSide } from "@bibliothecadao/eternum"; +import { BattleSide, ID } from "@bibliothecadao/eternum"; import { ComponentValue } from "@dojoengine/recs"; import { useState } from "react"; import { BattleDetails } from "./BattleDetails"; @@ -12,7 +12,7 @@ import { TroopRow } from "./Troops"; export const BattleSideView = ({ battleSide, - battleId, + battleEntityId, showBattleDetails, ownSideArmies, ownSideTroopsUpdated, @@ -21,11 +21,11 @@ export const BattleSideView = ({ isActive, }: { battleSide: BattleSide; - battleId: bigint | undefined; + battleEntityId: ID | undefined; showBattleDetails: boolean; ownSideArmies: (ArmyInfo | undefined)[]; ownSideTroopsUpdated: ComponentValue["troops"] | undefined; - ownArmyEntityId: bigint | undefined; + ownArmyEntityId: ID | undefined; structure: Structure | undefined; isActive: boolean; }) => { @@ -38,15 +38,15 @@ export const BattleSideView = ({ const [loading, setLoading] = useState(false); - const ownArmy = useArmyByArmyEntityId(ownArmyEntityId || 0n); + const ownArmy = useArmyByArmyEntityId(ownArmyEntityId || 0); - const joinBattle = async (side: BattleSide, armyId: bigint) => { + const joinBattle = async (side: BattleSide, armyId: ID) => { if (ownArmyEntityId) { setLoading(true); await battle_join({ signer: account, army_id: armyId, - battle_id: battleId!, + battle_id: battleEntityId!, battle_side: BigInt(side), }); setLoading(false); @@ -61,12 +61,12 @@ export const BattleSideView = ({ >
0} /> - {Boolean(battleId) && Boolean(ownArmyEntityId) && isActive && ownArmy.battle_id === 0n && ( + {Boolean(battleEntityId) && Boolean(ownArmyEntityId) && isActive && ownArmy.battle_id === 0 && (
)}
- {showBattleDetails && battleId ? ( + {showBattleDetails && battleEntityId ? ( ) : ( diff --git a/client/src/ui/modules/military/battle-view/BattleView.tsx b/client/src/ui/modules/military/battle-view/BattleView.tsx index 2a1e9b121..4f1c8f15c 100644 --- a/client/src/ui/modules/military/battle-view/BattleView.tsx +++ b/client/src/ui/modules/military/battle-view/BattleView.tsx @@ -28,23 +28,23 @@ export const BattleView = () => { const battlePosition = { x: clickedHex?.contractPos.col || 0, y: clickedHex?.contractPos.row || 0 }; // get updated army for when a battle starts: we need to have the updated component to have the correct battle_id - const updatedTarget = useArmyByArmyEntityId(battleView?.targetArmy || 0n); + const updatedTarget = useArmyByArmyEntityId(battleView?.targetArmy || 0); const targetArmy = useMemo(() => { - const tempBattleManager = new BattleManager(updatedTarget?.battle_id || 0n, dojo); + const tempBattleManager = new BattleManager(updatedTarget?.battle_id || 0, dojo); const updatedBattle = tempBattleManager.getUpdatedBattle(currentTimestamp!); return tempBattleManager.getUpdatedArmy(updatedTarget, updatedBattle); }, [updatedTarget, battleView?.targetArmy]); const battleManager = useBattleManager( - battleView?.battle ? battleView?.battle : battleView?.engage ? 0n : targetArmy?.battle_id || 0n, + battleView?.battleEntityId ? battleView?.battleEntityId : battleView?.engage ? 0 : targetArmy?.battle_id || 0, ); const armies = useMemo(() => { if (!battleManager.isBattle()) { return { armiesInBattle: [], userArmiesInBattle: [] }; } - const armiesInBattle = armiesByBattleId(battleManager?.battleId || 0n); + const armiesInBattle = armiesByBattleId(battleManager?.battleEntityId || 0); const userArmiesInBattle = armiesInBattle.filter((army) => army.isMine); return { armiesInBattle, userArmiesInBattle }; }, [battleManager]); @@ -54,7 +54,7 @@ export const BattleView = () => { : BattleSide[BattleSide.Attack]; const ownArmyBattleStarter = useMemo( - () => getAliveArmy(battleView!.ownArmyEntityId || 0n), + () => getAliveArmy(battleView!.ownArmyEntityId || 0), [battleView!.ownArmyEntityId], ); @@ -71,9 +71,7 @@ export const BattleView = () => { const battleAdjusted = useMemo(() => { if (!battleManager) return undefined; return battleManager!.getUpdatedBattle(currentTimestamp!); - }, [currentTimestamp, battleManager, battleManager?.battleId, armies.armiesInBattle, battleView]); - - const armiesAtPosition = getArmiesAtPosition(); + }, [currentTimestamp, battleManager, battleManager?.battleEntityId, armies.armiesInBattle, battleView]); const attackerHealth = battleAdjusted ? { @@ -100,9 +98,9 @@ export const BattleView = () => { const defenderTroops = battleAdjusted ? battleAdjusted!.defence_army.troops : targetArmy?.troops; const structure = - battleView?.engage && !battleView?.battle && !battleView.targetArmy + battleView?.engage && !battleView?.battleEntityId && !battleView.targetArmy ? getStructure({ x: battlePosition.x, y: battlePosition.y }) - : getStructureByEntityId(defenderArmies.find((army) => army?.protectee)?.protectee?.protectee_id || 0n); + : getStructureByEntityId(defenderArmies.find((army) => army?.protectee)?.protectee?.protectee_id || 0); const isActive = battleManager?.isBattleOngoing(currentTimestamp!); diff --git a/client/src/ui/modules/military/battle-view/LockedResources.tsx b/client/src/ui/modules/military/battle-view/LockedResources.tsx index 394ce0aa3..a41cf0300 100644 --- a/client/src/ui/modules/military/battle-view/LockedResources.tsx +++ b/client/src/ui/modules/military/battle-view/LockedResources.tsx @@ -1,11 +1,12 @@ import { InventoryResources } from "@/ui/components/resources/InventoryResources"; +import { ID } from "@bibliothecadao/eternum"; export const LockedResources = ({ attackersResourcesEscrowEntityId, defendersResourcesEscrowEntityId, }: { - attackersResourcesEscrowEntityId: bigint; - defendersResourcesEscrowEntityId: bigint; + attackersResourcesEscrowEntityId: ID; + defendersResourcesEscrowEntityId: ID; }) => { return (
diff --git a/client/src/ui/modules/military/battle-view/SelectActiveArmy.tsx b/client/src/ui/modules/military/battle-view/SelectActiveArmy.tsx deleted file mode 100644 index 705a01dd2..000000000 --- a/client/src/ui/modules/military/battle-view/SelectActiveArmy.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { ArmyInfo } from "@/hooks/helpers/useArmies"; -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/ui/elements/Select"; - -export const SelectActiveArmy = ({ - localSelectedUnit, - setLocalSelectedUnit, - userAttackingArmies, -}: { - localSelectedUnit: bigint | undefined; - setLocalSelectedUnit: (val: any) => void; - userAttackingArmies: ArmyInfo[]; -}) => { - return ( -
- -
- ); -}; diff --git a/client/src/ui/modules/military/battle-view/Troops.tsx b/client/src/ui/modules/military/battle-view/Troops.tsx index e8d9ca7c8..5501c9a01 100644 --- a/client/src/ui/modules/military/battle-view/Troops.tsx +++ b/client/src/ui/modules/military/battle-view/Troops.tsx @@ -29,7 +29,7 @@ export const TroopRow = ({ ); }; -export const TroopCard = ({ +const TroopCard = ({ count, id, className, diff --git a/client/src/ui/modules/navigation/BottomNavigation.tsx b/client/src/ui/modules/navigation/BottomNavigation.tsx index 91cef5914..20e3f4bf2 100644 --- a/client/src/ui/modules/navigation/BottomNavigation.tsx +++ b/client/src/ui/modules/navigation/BottomNavigation.tsx @@ -1,7 +1,9 @@ import { useEntities } from "@/hooks/helpers/useEntities"; +import { QuestStatus, useQuestClaimStatus, useQuests, useUnclaimedQuestsCount } from "@/hooks/helpers/useQuests"; import { useQuestStore } from "@/hooks/store/useQuestStore"; import useRealmStore from "@/hooks/store/useRealmStore"; import useUIStore from "@/hooks/store/useUIStore"; +import { QuestId } from "@/ui/components/quest/questDetails"; import CircleButton from "@/ui/elements/CircleButton"; import { isRealmSelected } from "@/ui/utils/utils"; import clsx from "clsx"; @@ -10,21 +12,16 @@ import { ArrowDown } from "lucide-react"; import { useMemo } from "react"; import { useLocation } from "wouter"; import { guilds, leaderboard, quests as questsWindow } from "../../components/navigation/Config"; +import { Assistant } from "../assistant/Assistant"; +import { Guilds } from "../guilds/Guilds"; +import { Leaderboard } from "../leaderboard/LeaderBoard"; +import { Questing } from "../questing/Questing"; import { BuildingThumbs } from "./LeftNavigationModule"; -import { QuestStatus, useUnclaimedQuestsCount, useQuests, useQuestClaimStatus } from "@/hooks/helpers/useQuests"; -import { QuestId } from "@/ui/components/quest/questDetails"; export enum MenuEnum { - realm = "realm", - worldMap = "world-map", military = "military", construction = "construction", - trade = "trade", - resources = "resources", - bank = "bank", worldStructures = "worldStructures", - structures = "structures", - leaderboard = "leaderboard", entityDetails = "entityDetails", } @@ -110,19 +107,28 @@ export const BottomNavigation = () => { }; return ( - -
-
- {secondaryNavigation.map((a, index) => ( -
{a.button}
- ))} -
+ <> +
+ + + +
- + + +
+
+ {secondaryNavigation.map((a, index) => ( +
{a.button}
+ ))} +
+
+
+ ); }; diff --git a/client/src/ui/modules/navigation/LeftNavigationModule.tsx b/client/src/ui/modules/navigation/LeftNavigationModule.tsx index 5e0b39f2f..c5337e9d1 100644 --- a/client/src/ui/modules/navigation/LeftNavigationModule.tsx +++ b/client/src/ui/modules/navigation/LeftNavigationModule.tsx @@ -1,16 +1,16 @@ import { useArmiesByEntityOwner } from "@/hooks/helpers/useArmies"; import { getEntitiesUtils } from "@/hooks/helpers/useEntities"; +import { useQuestClaimStatus } from "@/hooks/helpers/useQuests"; import { useStamina } from "@/hooks/helpers/useStamina"; -import useBlockchainStore from "@/hooks/store/useBlockchainStore"; import { useQuestStore } from "@/hooks/store/useQuestStore"; import useUIStore from "@/hooks/store/useUIStore"; import { SelectPreviewBuildingMenu } from "@/ui/components/construction/SelectPreviewBuilding"; +import { QuestId } from "@/ui/components/quest/questDetails"; import { StructureConstructionMenu } from "@/ui/components/structures/construction/StructureConstructionMenu"; import { BaseContainer } from "@/ui/containers/BaseContainer"; import Button from "@/ui/elements/Button"; import { EntityDetails } from "@/ui/modules/entity-details/EntityDetails"; import { Military } from "@/ui/modules/military/Military"; -import { EternumGlobalConfig } from "@bibliothecadao/eternum"; import clsx from "clsx"; import { motion } from "framer-motion"; import { debounce } from "lodash"; @@ -20,14 +20,8 @@ import { useLocation } from "wouter"; import useRealmStore from "../../../hooks/store/useRealmStore"; import { construction, military, quests as questsPopup, worldStructures } from "../../components/navigation/Config"; import CircleButton from "../../elements/CircleButton"; -import { Assistant } from "../assistant/Assistant"; -import { Guilds } from "../guilds/Guilds"; -import { Leaderboard } from "../leaderboard/LeaderBoard"; -import { Questing } from "../questing/Questing"; import { WorldStructuresMenu } from "../world-structures/WorldStructuresMenu"; import { MenuEnum } from "./BottomNavigation"; -import { useQuestClaimStatus } from "@/hooks/helpers/useQuests"; -import { QuestId } from "@/ui/components/quest/questDetails"; export const BuildingThumbs = { hex: "/images/buildings/thumb/question.png", @@ -51,7 +45,6 @@ export enum View { MilitaryView, EntityView, ConstructionView, - StructureView, WorldStructuresView, } @@ -210,15 +203,8 @@ export const LeftNavigationModule = () => { return ( <> -
- - - - -
-
{ @@ -233,7 +219,9 @@ export const LeftNavigationModule = () => { }} onPointerLeave={debouncedSetIsOffscreen} > - + {view === View.EntityView && } {view === View.MilitaryView && } {!isWorldView && view === View.ConstructionView && } @@ -244,7 +232,7 @@ export const LeftNavigationModule = () => { variants={slideLeft} initial="hidden" animate="visible" - className="gap-2 flex flex-col justify-center self-center" + className="gap-2 flex flex-col justify-center self-center pointer-events-auto" >
- + {view === View.ResourceTable ? (
diff --git a/client/src/ui/modules/navigation/TopMiddleNavigation.tsx b/client/src/ui/modules/navigation/TopMiddleNavigation.tsx index 4a4a9ed1d..d8ca1593e 100644 --- a/client/src/ui/modules/navigation/TopMiddleNavigation.tsx +++ b/client/src/ui/modules/navigation/TopMiddleNavigation.tsx @@ -9,6 +9,7 @@ import { BASE_POPULATION_CAPACITY, BuildingType, EternumGlobalConfig, + ID, STOREHOUSE_CAPACITY, StructureType, } from "@bibliothecadao/eternum"; @@ -19,11 +20,11 @@ import { useMemo } from "react"; import { useLocation } from "wouter"; import useBlockchainStore from "../../../hooks/store/useBlockchainStore"; +import { QuestStatus } from "@/hooks/helpers/useQuests"; import { useQuestStore } from "@/hooks/store/useQuestStore"; +import { QuestId } from "@/ui/components/quest/questDetails"; import { useComponentValue } from "@dojoengine/react"; import clsx from "clsx"; -import { QuestStatus } from "@/hooks/helpers/useQuests"; -import { QuestId } from "@/ui/components/quest/questDetails"; import { motion } from "framer-motion"; const slideDown = { @@ -67,33 +68,30 @@ export const TopMiddleNavigation = () => { return location.includes(`/hex`); }, [location]); - const goToHexView = (entityId: any) => { - const structure = structures.find((structure) => structure.entity_id?.toString() === entityId); + const goToHexView = (entityId: ID) => { + const structure = structures.find((structure) => structure.entity_id === entityId); setIsLoadingScreenEnabled(true); setTimeout(() => { setLocation(`/hex?col=${structure!.position.x}&row=${structure!.position.y}`); - setRealmEntityId(BigInt(entityId)); + setRealmEntityId(entityId); }, 300); }; - const goToMapView = (entityId: any) => { + const goToMapView = (entityId: ID) => { const contractPosition = getComponentValue(setup.components.Position, getEntityIdFromKeys([BigInt(entityId)])); moveCameraToColRow(Number(contractPosition?.x), Number(contractPosition?.y)); - setRealmEntityId(BigInt(entityId)); + setRealmEntityId(entityId); }; const setTooltip = useUIStore((state) => state.setTooltip); - const population = useComponentValue( - setup.components.Population, - getEntityIdFromKeys([BigInt(realmEntityId || "0")]), - ); + const population = useComponentValue(setup.components.Population, getEntityIdFromKeys([BigInt(realmEntityId || 0)])); const storehouses = useMemo(() => { const quantity = getComponentValue( setup.components.BuildingQuantityv2, - getEntityIdFromKeys([BigInt(realmEntityId || "0"), BigInt(BuildingType.Storehouse)]), + getEntityIdFromKeys([BigInt(realmEntityId || 0), BigInt(BuildingType.Storehouse)]), )?.value || 0; return quantity * STOREHOUSE_CAPACITY + STOREHOUSE_CAPACITY; @@ -110,8 +108,8 @@ export const TopMiddleNavigation = () => {