create-dubhe 1.2.0-pre.98 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/package.json +16 -16
- package/templates/101/sui-template/docker-compose.testnet.yml +73 -0
- package/templates/101/sui-template/packages/client/src/app/page.tsx +545 -41
- package/templates/101/sui-template/packages/client/src/app/providers.tsx +12 -4
- package/templates/101/sui-template/packages/contracts/Pub.localnet.toml +4 -4
- package/templates/101/sui-template/packages/contracts/counter.lock.json +20 -0
- package/templates/101/sui-template/packages/contracts/deployment.ts +8 -3
- package/templates/101/sui-template/packages/contracts/dubhe.config.json +59 -13
- package/templates/101/sui-template/packages/contracts/dubhe.config.ts +1 -4
- package/templates/101/sui-template/packages/contracts/metadata.json +1015 -68
- package/templates/101/sui-template/packages/contracts/package.json +7 -4
- package/templates/101/sui-template/packages/contracts/src/counter/sources/codegen/dapp_key.move +45 -31
- package/templates/101/sui-template/packages/contracts/src/counter/sources/codegen/error.move +8 -0
- package/templates/101/sui-template/packages/contracts/src/counter/sources/codegen/genesis.move +30 -13
- package/templates/101/sui-template/packages/contracts/src/counter/sources/codegen/init_test.move +19 -14
- package/templates/101/sui-template/packages/contracts/src/counter/sources/codegen/resources/counter2.move +198 -0
- package/templates/101/sui-template/packages/contracts/src/counter/sources/codegen/resources/counter2withkey.move +90 -0
- package/templates/101/sui-template/packages/contracts/src/counter/sources/codegen/resources/value.move +30 -20
- package/templates/101/sui-template/packages/contracts/src/counter/sources/codegen/user_storage_init.move +26 -0
- package/templates/101/sui-template/packages/contracts/src/counter/sources/scripts/deploy_hook.move +6 -11
- package/templates/101/sui-template/packages/contracts/src/counter/sources/systems/counter.move +23 -11
- package/templates/101/sui-template/packages/contracts/src/counter/sources/tests/counter.move +15 -14
- package/templates/101/sui-template/packages/contracts/src/dubhe/Move.lock +33 -30
- package/templates/101/sui-template/packages/contracts/src/dubhe/Move.toml +8 -3
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/codegen/dapp_key.move +45 -31
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/codegen/error.move +170 -0
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/codegen/genesis.move +16 -13
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/codegen/init_test.move +8 -14
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/core/account_key.move +1 -3
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/core/dapp_service.move +1776 -137
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/core/data_key.move +1 -20
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/core/events.move +864 -25
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/scripts/deploy_hook.move +15 -16
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/scripts/migrate.move +0 -3
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/systems/address_system.move +25 -17
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/systems/dapp_system.move +2802 -343
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/systems/utils.move +1 -1
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/tests/address.move +173 -55
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/tests/dapp_test.move +769 -0
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/tests/fee_test.move +2965 -0
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/tests/integration_test.move +303 -0
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/tests/listing_test.move +1422 -0
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/tests/scene_session_test.move +269 -0
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/tests/session_test.move +624 -0
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/tests/storage_test.move +700 -0
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/tests/typed_object_test.move +177 -0
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/tests/typed_scene_test.move +452 -0
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/tests/user_storage_test.move +160 -0
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/utils/math.move +4 -3
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/utils/type_info.move +2 -2
- package/templates/contract/sui-template/dubhe.config.ts +0 -1
- package/templates/contract/sui-template/package.json +3 -3
- package/templates/contract/sui-template/src/dubhe/Move.lock +33 -30
- package/templates/contract/sui-template/src/dubhe/Move.toml +8 -3
- package/templates/contract/sui-template/src/dubhe/sources/codegen/dapp_key.move +45 -31
- package/templates/contract/sui-template/src/dubhe/sources/codegen/error.move +170 -0
- package/templates/contract/sui-template/src/dubhe/sources/codegen/genesis.move +16 -13
- package/templates/contract/sui-template/src/dubhe/sources/codegen/init_test.move +8 -14
- package/templates/contract/sui-template/src/dubhe/sources/core/account_key.move +1 -3
- package/templates/contract/sui-template/src/dubhe/sources/core/dapp_service.move +1776 -137
- package/templates/contract/sui-template/src/dubhe/sources/core/data_key.move +1 -20
- package/templates/contract/sui-template/src/dubhe/sources/core/events.move +864 -25
- package/templates/contract/sui-template/src/dubhe/sources/scripts/deploy_hook.move +15 -16
- package/templates/contract/sui-template/src/dubhe/sources/scripts/migrate.move +0 -3
- package/templates/contract/sui-template/src/dubhe/sources/systems/address_system.move +25 -17
- package/templates/contract/sui-template/src/dubhe/sources/systems/dapp_system.move +2802 -343
- package/templates/contract/sui-template/src/dubhe/sources/systems/utils.move +1 -1
- package/templates/contract/sui-template/src/dubhe/sources/tests/address.move +173 -55
- package/templates/contract/sui-template/src/dubhe/sources/tests/dapp_test.move +769 -0
- package/templates/contract/sui-template/src/dubhe/sources/tests/fee_test.move +2965 -0
- package/templates/contract/sui-template/src/dubhe/sources/tests/integration_test.move +303 -0
- package/templates/contract/sui-template/src/dubhe/sources/tests/listing_test.move +1422 -0
- package/templates/contract/sui-template/src/dubhe/sources/tests/scene_session_test.move +269 -0
- package/templates/contract/sui-template/src/dubhe/sources/tests/session_test.move +624 -0
- package/templates/contract/sui-template/src/dubhe/sources/tests/storage_test.move +700 -0
- package/templates/contract/sui-template/src/dubhe/sources/tests/typed_object_test.move +177 -0
- package/templates/contract/sui-template/src/dubhe/sources/tests/typed_scene_test.move +452 -0
- package/templates/contract/sui-template/src/dubhe/sources/tests/user_storage_test.move +160 -0
- package/templates/contract/sui-template/src/dubhe/sources/utils/math.move +4 -3
- package/templates/contract/sui-template/src/dubhe/sources/utils/type_info.move +2 -2
- package/templates/contract/sui-template/src/template/Move.toml +12 -0
- package/templates/contract/sui-template/src/template/sources/codegen/dapp_key.move +47 -0
- package/templates/contract/sui-template/src/template/sources/codegen/genesis.move +34 -0
- package/templates/contract/sui-template/src/template/sources/codegen/init_test.move +23 -0
- package/templates/contract/sui-template/src/template/sources/codegen/user_storage_init.move +27 -0
- package/templates/contract/sui-template/src/template/sources/scripts/deploy_hook.move +13 -0
- package/templates/contract/sui-template/src/template/sources/scripts/migrate.move +7 -0
- package/templates/nextjs/sui-card-duel/.gitignore_ +51 -0
- package/templates/nextjs/sui-card-duel/README.md +213 -0
- package/templates/nextjs/sui-card-duel/docker-compose.yml +34 -0
- package/templates/nextjs/sui-card-duel/mprocs.yaml +17 -0
- package/templates/nextjs/sui-card-duel/package.json +43 -0
- package/templates/nextjs/sui-card-duel/packages/client/.gitignore_ +48 -0
- package/templates/nextjs/sui-card-duel/packages/client/.prettierignore +1 -0
- package/templates/nextjs/sui-card-duel/packages/client/.prettierrc.json +8 -0
- package/templates/nextjs/sui-card-duel/packages/client/eslint.config.mjs +22 -0
- package/templates/nextjs/sui-card-duel/packages/client/next.config.mjs +8 -0
- package/templates/nextjs/sui-card-duel/packages/client/package.json +47 -0
- package/templates/nextjs/sui-card-duel/packages/client/postcss.config.mjs +8 -0
- package/templates/nextjs/sui-card-duel/packages/client/src/app/admin/ArenaPanel.tsx +307 -0
- package/templates/nextjs/sui-card-duel/packages/client/src/app/admin/page.tsx +622 -0
- package/templates/nextjs/sui-card-duel/packages/client/src/app/brawl/[id]/page.tsx +559 -0
- package/templates/nextjs/sui-card-duel/packages/client/src/app/collection/page.tsx +202 -0
- package/templates/nextjs/sui-card-duel/packages/client/src/app/components/CardView.tsx +66 -0
- package/templates/nextjs/sui-card-duel/packages/client/src/app/components/GameShell.tsx +294 -0
- package/templates/nextjs/sui-card-duel/packages/client/src/app/components/icons.tsx +101 -0
- package/templates/nextjs/sui-card-duel/packages/client/src/app/duel/[id]/page.tsx +477 -0
- package/templates/nextjs/sui-card-duel/packages/client/src/app/favicon.ico +0 -0
- package/templates/nextjs/sui-card-duel/packages/client/src/app/globals.css +85 -0
- package/templates/nextjs/sui-card-duel/packages/client/src/app/hooks/useGame.ts +313 -0
- package/templates/nextjs/sui-card-duel/packages/client/src/app/layout.tsx +24 -0
- package/templates/nextjs/sui-card-duel/packages/client/src/app/leaderboard/page.tsx +123 -0
- package/templates/nextjs/sui-card-duel/packages/client/src/app/lib/game.ts +77 -0
- package/templates/nextjs/sui-card-duel/packages/client/src/app/lib/scenes.ts +226 -0
- package/templates/nextjs/sui-card-duel/packages/client/src/app/market/page.tsx +418 -0
- package/templates/nextjs/sui-card-duel/packages/client/src/app/page.tsx +427 -0
- package/templates/nextjs/sui-card-duel/packages/client/src/app/providers.tsx +69 -0
- package/templates/nextjs/sui-card-duel/packages/client/tailwind.config.ts +21 -0
- package/templates/nextjs/sui-card-duel/packages/client/tsconfig.json +30 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/.gitignore_ +51 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/.prettierignore +1 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/.prettierrc.json +8 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/Dockerfile +5 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/Pub.localnet.toml +13 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/card_duel.lock.json +66 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/docker-compose.yml +34 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/dubhe.config.ts +150 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/logs/combined.log +31383 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/package.json +49 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/scripts/config.ts +17 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/scripts/e2e-brawl.ts +270 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/scripts/e2e-duel.ts +272 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/scripts/e2e-lobby.ts +177 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/scripts/e2e-market.ts +219 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/scripts/e2e-session.ts +342 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/scripts/query-dapp-revenue.ts +95 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/scripts/seed.ts +92 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/scripts/withdraw-dapp-revenue.ts +56 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/Move.toml +15 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/dapp_key.move +46 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/enums/card_kind.move +47 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/enums/match_state.move +37 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/enums/rarity.move +37 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/error.move +126 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/genesis.move +33 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/init_test.move +23 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/objects/arena.move +137 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/permits/brawl_permit.move +125 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/permits/duel_permit.move +125 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/resources/battle_state.move +255 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/resources/card.move +282 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/resources/deck.move +64 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/resources/game_config.move +267 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/resources/gold.move +205 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/resources/profile.move +255 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/scenes/brawl.move +313 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/scenes/duel.move +313 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/user_storage_init.move +26 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/scripts/deploy_hook.move +32 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/scripts/migrate.move +7 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/systems/arena_system.move +57 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/systems/brawl_system.move +559 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/systems/card_system.move +146 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/systems/duel_system.move +515 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/systems/market_system.move +115 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/systems/player_system.move +37 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/tests/brawl_tests.move +385 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/tests/duel_tests.move +656 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/tests/test_helpers.move +31 -0
- package/templates/nextjs/sui-card-duel/packages/contracts/sui-indexer-schema.graphql +5973 -0
- package/templates/nextjs/sui-card-duel/pnpm-workspace.yaml +2 -0
- package/templates/nextjs/sui-farm/.gitignore_ +51 -0
- package/templates/nextjs/sui-farm/README.md +15 -0
- package/templates/nextjs/sui-farm/UPGRADE_NOTES.md +97 -0
- package/templates/nextjs/sui-farm/docker-compose.yml +34 -0
- package/templates/nextjs/sui-farm/mprocs.yaml +17 -0
- package/templates/nextjs/sui-farm/package.json +43 -0
- package/templates/nextjs/sui-farm/packages/client/.gitignore_ +48 -0
- package/templates/nextjs/sui-farm/packages/client/.prettierignore +1 -0
- package/templates/nextjs/sui-farm/packages/client/.prettierrc.json +8 -0
- package/templates/nextjs/sui-farm/packages/client/eslint.config.mjs +22 -0
- package/templates/nextjs/sui-farm/packages/client/next.config.mjs +8 -0
- package/templates/nextjs/sui-farm/packages/client/package.json +47 -0
- package/templates/nextjs/sui-farm/packages/client/postcss.config.mjs +8 -0
- package/templates/nextjs/sui-farm/packages/client/src/app/admin/page.tsx +618 -0
- package/templates/nextjs/sui-farm/packages/client/src/app/components/FarmLand.tsx +526 -0
- package/templates/nextjs/sui-farm/packages/client/src/app/components/FarmPlotCard.tsx +215 -0
- package/templates/nextjs/sui-farm/packages/client/src/app/components/PetAvatar.tsx +868 -0
- package/templates/nextjs/sui-farm/packages/client/src/app/components/PetPanel.tsx +1360 -0
- package/templates/nextjs/sui-farm/packages/client/src/app/components/PlantModal.tsx +147 -0
- package/templates/nextjs/sui-farm/packages/client/src/app/components/ProxyCard.tsx +684 -0
- package/templates/nextjs/sui-farm/packages/client/src/app/components/RanchLand.tsx +822 -0
- package/templates/nextjs/sui-farm/packages/client/src/app/components/ResourceHUD.tsx +125 -0
- package/templates/nextjs/sui-farm/packages/client/src/app/components/ShopPanel.tsx +232 -0
- package/templates/nextjs/sui-farm/packages/client/src/app/components/icons/GameIcons.tsx +574 -0
- package/templates/nextjs/sui-farm/packages/client/src/app/favicon.ico +0 -0
- package/templates/nextjs/sui-farm/packages/client/src/app/globals.css +423 -0
- package/templates/nextjs/sui-farm/packages/client/src/app/hooks/useWorldPermitId.ts +66 -0
- package/templates/nextjs/sui-farm/packages/client/src/app/layout.tsx +23 -0
- package/templates/nextjs/sui-farm/packages/client/src/app/leaderboard/page.tsx +185 -0
- package/templates/nextjs/sui-farm/packages/client/src/app/lib/crops.ts +97 -0
- package/templates/nextjs/sui-farm/packages/client/src/app/market/page.tsx +763 -0
- package/templates/nextjs/sui-farm/packages/client/src/app/page.tsx +1173 -0
- package/templates/nextjs/sui-farm/packages/client/src/app/providers.tsx +69 -0
- package/templates/nextjs/sui-farm/packages/client/src/app/state/index.tsx +5 -0
- package/templates/nextjs/sui-farm/packages/client/tailwind.config.ts +25 -0
- package/templates/nextjs/sui-farm/packages/client/tsconfig.json +30 -0
- package/templates/nextjs/sui-farm/packages/contracts/.gitignore_ +51 -0
- package/templates/nextjs/sui-farm/packages/contracts/.prettierignore +1 -0
- package/templates/nextjs/sui-farm/packages/contracts/.prettierrc.json +8 -0
- package/templates/nextjs/sui-farm/packages/contracts/Dockerfile +5 -0
- package/templates/nextjs/sui-farm/packages/contracts/Pub.localnet.toml +13 -0
- package/templates/nextjs/sui-farm/packages/contracts/counter.lock.json +14 -0
- package/templates/nextjs/sui-farm/packages/contracts/docker-compose.yml +34 -0
- package/templates/nextjs/sui-farm/packages/contracts/dubhe.config.ts +178 -0
- package/templates/nextjs/sui-farm/packages/contracts/harvest.lock.json +120 -0
- package/templates/nextjs/sui-farm/packages/contracts/package.json +48 -0
- package/templates/nextjs/sui-farm/packages/contracts/scripts/config.ts +17 -0
- package/templates/nextjs/sui-farm/packages/contracts/scripts/query-dapp-revenue.ts +95 -0
- package/templates/nextjs/sui-farm/packages/contracts/scripts/read-permit.ts +72 -0
- package/templates/nextjs/sui-farm/packages/contracts/scripts/seed.ts +85 -0
- package/templates/nextjs/sui-farm/packages/contracts/scripts/withdraw-dapp-revenue.ts +56 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/counter/Move.toml +14 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/counter/sources/codegen/dapp_key.move +31 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/counter/sources/codegen/error.move +10 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/counter/sources/codegen/genesis.move +33 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/counter/sources/codegen/init_test.move +23 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/counter/sources/codegen/resources/counter1.move +64 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/counter/sources/codegen/resources/counter2.move +70 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/counter/sources/codegen/user_storage_init.move +26 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/counter/sources/scripts/deploy_hook.move +8 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/counter/sources/scripts/migrate.move +8 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/counter/sources/systems/counter.move +13 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/counter/sources/tests/counter.move +28 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/Move.toml +14 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/dapp_key.move +46 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/enums/crop_type.move +47 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/enums/egg_type.move +42 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/enums/pet_rarity.move +37 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/enums/pet_species.move +52 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/error.move +110 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/genesis.move +33 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/init_test.move +23 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/permits/world.move +125 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/carrot.move +136 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/carrot_seed.move +80 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/common_egg.move +136 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/corn.move +136 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/corn_seed.move +80 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/crow_charges.move +162 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/crow_damage.move +207 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/farm_plot.move +261 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/gold.move +80 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/pet.move +467 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/pet_config.move +372 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/pet_hatch.move +162 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/pet_slot_index.move +83 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/pet_slots.move +64 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/profile.move +162 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/pumpkin.move +136 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/pumpkin_seed.move +80 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/rare_egg.move +136 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/scarecrow.move +64 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/season_config.move +197 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/season_stats.move +64 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/seasonal_egg.move +136 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/shop_config.move +267 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/trophy.move +245 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/wheat.move +136 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/wheat_seed.move +80 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/world_permit_id.move +64 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/user_storage_init.move +26 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/scripts/deploy_hook.move +45 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/scripts/migrate.move +7 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/systems/crow_system.move +96 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/systems/farm_system.move +182 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/systems/market_system.move +172 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/systems/pet_system.move +495 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/systems/season_system.move +70 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/systems/shop_system.move +112 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/systems/world_system.move +34 -0
- package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/tests/farm_tests.move +1192 -0
- package/templates/nextjs/sui-farm/pnpm-workspace.yaml +2 -0
- package/templates/nextjs/sui-template/packages/client/src/app/components/ProxyCard.tsx +683 -0
- package/templates/nextjs/sui-template/packages/client/src/app/page.tsx +510 -5
- package/templates/nextjs/sui-template/packages/client/src/app/providers.tsx +13 -5
- package/templates/nextjs/sui-template/packages/contracts/Pub.localnet.toml +4 -4
- package/templates/nextjs/sui-template/packages/contracts/counter.lock.json +14 -0
- package/templates/nextjs/sui-template/packages/contracts/deployment.ts +8 -3
- package/templates/nextjs/sui-template/packages/contracts/dubhe.config.json +9 -9
- package/templates/nextjs/sui-template/packages/contracts/dubhe.config.ts +0 -4
- package/templates/nextjs/sui-template/packages/contracts/metadata.json +180 -124
- package/templates/nextjs/sui-template/packages/contracts/package.json +8 -4
- package/templates/nextjs/sui-template/packages/contracts/src/counter/Move.toml +4 -0
- package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/codegen/dapp_key.move +45 -31
- package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/codegen/error.move +10 -0
- package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/codegen/genesis.move +30 -13
- package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/codegen/init_test.move +19 -14
- package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/codegen/resources/counter1.move +30 -20
- package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/codegen/resources/counter2.move +35 -24
- package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/codegen/user_storage_init.move +26 -0
- package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/scripts/deploy_hook.move +6 -10
- package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/systems/counter.move +7 -20
- package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/tests/counter.move +14 -27
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/Move.lock +33 -30
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/Move.toml +8 -3
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/codegen/dapp_key.move +45 -31
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/codegen/error.move +170 -0
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/codegen/genesis.move +16 -13
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/codegen/init_test.move +8 -14
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/core/account_key.move +1 -3
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/core/dapp_service.move +1776 -137
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/core/data_key.move +1 -20
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/core/events.move +864 -25
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/scripts/deploy_hook.move +15 -16
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/scripts/migrate.move +0 -3
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/systems/address_system.move +25 -17
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/systems/dapp_system.move +2802 -343
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/systems/utils.move +1 -1
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/address.move +173 -55
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/dapp_test.move +769 -0
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/fee_test.move +2965 -0
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/integration_test.move +303 -0
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/listing_test.move +1422 -0
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/scene_session_test.move +269 -0
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/session_test.move +624 -0
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/storage_test.move +700 -0
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/typed_object_test.move +177 -0
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/typed_scene_test.move +452 -0
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/user_storage_test.move +160 -0
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/utils/math.move +4 -3
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/utils/type_info.move +2 -2
- package/templates/101/sui-template/packages/contracts/src/counter/Move.lock +0 -41
- package/templates/101/sui-template/packages/contracts/src/counter/Published.toml +0 -9
- package/templates/101/sui-template/packages/contracts/src/counter/sources/codegen/errors.move +0 -12
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/codegen/errors.move +0 -140
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/codegen/resources/dapp_fee_config.move +0 -186
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/codegen/resources/dapp_fee_state.move +0 -306
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/codegen/resources/dapp_metadata.move +0 -396
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/codegen/resources/dubhe_config.move +0 -246
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/core/dapp_store.move +0 -29
- package/templates/101/sui-template/packages/contracts/src/dubhe/sources/systems/session_system.move +0 -44
- package/templates/contract/sui-template/src/dubhe/sources/codegen/errors.move +0 -140
- package/templates/contract/sui-template/src/dubhe/sources/codegen/resources/dapp_fee_config.move +0 -186
- package/templates/contract/sui-template/src/dubhe/sources/codegen/resources/dapp_fee_state.move +0 -306
- package/templates/contract/sui-template/src/dubhe/sources/codegen/resources/dapp_metadata.move +0 -396
- package/templates/contract/sui-template/src/dubhe/sources/codegen/resources/dubhe_config.move +0 -246
- package/templates/contract/sui-template/src/dubhe/sources/core/dapp_store.move +0 -29
- package/templates/contract/sui-template/src/dubhe/sources/systems/session_system.move +0 -44
- package/templates/nextjs/sui-template/packages/contracts/src/counter/Move.lock +0 -47
- package/templates/nextjs/sui-template/packages/contracts/src/counter/Published.toml +0 -9
- package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/codegen/errors.move +0 -12
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/codegen/errors.move +0 -140
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/codegen/resources/dapp_fee_config.move +0 -186
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/codegen/resources/dapp_fee_state.move +0 -306
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/codegen/resources/dapp_metadata.move +0 -396
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/codegen/resources/dubhe_config.move +0 -246
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/core/dapp_store.move +0 -29
- package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/systems/session_system.move +0 -44
package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/tests/farm_tests.move
ADDED
|
@@ -0,0 +1,1192 @@
|
|
|
1
|
+
/// Comprehensive boundary tests for harvest game systems.
|
|
2
|
+
///
|
|
3
|
+
/// Coverage:
|
|
4
|
+
/// farm_system — plant (6 success + 5 failure cases)
|
|
5
|
+
/// — harvest (10 success + 4 failure cases)
|
|
6
|
+
/// shop_system — buy_seeds (5 success + 5 failure cases)
|
|
7
|
+
/// — buy_extra_plot (3 success + 3 failure cases)
|
|
8
|
+
/// — sell_crops (4 success + 4 failure cases)
|
|
9
|
+
/// crow_system — place_scarecrow (2 success + 2 failure cases)
|
|
10
|
+
///
|
|
11
|
+
/// Logic checks verified:
|
|
12
|
+
/// • plant always deducts exactly 1 seed and stores crop_yield as plot count
|
|
13
|
+
/// • harvest returns base yield with no bonus, 2× season bonus (SEASON_BONUS_PCT=200),
|
|
14
|
+
/// 30% crow_damage debuff, expired debuff, and all three combined
|
|
15
|
+
/// • harvest clears the plot and updates profile.total_earned + season_stats
|
|
16
|
+
/// • harvest boundary: exactly at harvest_at succeeds, one ms before fails
|
|
17
|
+
/// • seed prices from deploy_hook: wheat=5, corn=20, carrot=60, pumpkin=40, plot=200
|
|
18
|
+
/// • sell prices: wheat=8, corn=35, carrot=120, pumpkin=100
|
|
19
|
+
/// • max plots cap: 12; starting plots: 3
|
|
20
|
+
|
|
21
|
+
#[test_only]
|
|
22
|
+
module harvest::farm_tests {
|
|
23
|
+
use sui::clock;
|
|
24
|
+
use dubhe::dapp_service::{DappStorage, UserStorage};
|
|
25
|
+
use harvest::init_test;
|
|
26
|
+
use harvest::deploy_hook;
|
|
27
|
+
use harvest::farm_system;
|
|
28
|
+
use harvest::shop_system;
|
|
29
|
+
use harvest::crow_system;
|
|
30
|
+
use harvest::gold;
|
|
31
|
+
use harvest::wheat_seed;
|
|
32
|
+
use harvest::corn_seed;
|
|
33
|
+
use harvest::carrot_seed;
|
|
34
|
+
use harvest::pumpkin_seed;
|
|
35
|
+
use harvest::wheat;
|
|
36
|
+
use harvest::corn;
|
|
37
|
+
use harvest::carrot;
|
|
38
|
+
use harvest::pumpkin;
|
|
39
|
+
use harvest::profile;
|
|
40
|
+
use harvest::farm_plot;
|
|
41
|
+
use harvest::season_config;
|
|
42
|
+
use harvest::season_stats;
|
|
43
|
+
use harvest::crow_damage;
|
|
44
|
+
use harvest::scarecrow;
|
|
45
|
+
|
|
46
|
+
// ─── Constants (must match farm_system.move / deploy_hook.move) ──────────────
|
|
47
|
+
const CROP_WHEAT: u8 = 1;
|
|
48
|
+
const CROP_CORN: u8 = 2;
|
|
49
|
+
const CROP_CARROT: u8 = 3;
|
|
50
|
+
const CROP_PUMPKIN: u8 = 4;
|
|
51
|
+
|
|
52
|
+
const WHEAT_MS: u64 = 60_000; // 1 min
|
|
53
|
+
const CORN_MS: u64 = 120_000; // 2 min
|
|
54
|
+
const CARROT_MS: u64 = 240_000; // 4 min
|
|
55
|
+
const PUMPKIN_MS: u64 = 300_000; // 5 min
|
|
56
|
+
|
|
57
|
+
const WHEAT_YIELD: u64 = 6;
|
|
58
|
+
const CORN_YIELD: u64 = 4;
|
|
59
|
+
const CARROT_YIELD: u64 = 3;
|
|
60
|
+
const PUMPKIN_YIELD: u64 = 3;
|
|
61
|
+
|
|
62
|
+
// sell prices used in shop_system.move
|
|
63
|
+
const WHEAT_SELL: u64 = 8;
|
|
64
|
+
const CORN_SELL: u64 = 35;
|
|
65
|
+
const CARROT_SELL: u64 = 120;
|
|
66
|
+
const PUMPKIN_SELL: u64 = 100;
|
|
67
|
+
|
|
68
|
+
// seed prices set by deploy_hook
|
|
69
|
+
const WHEAT_PRICE: u64 = 5;
|
|
70
|
+
const CORN_PRICE: u64 = 20;
|
|
71
|
+
const CARROT_PRICE: u64 = 60;
|
|
72
|
+
const PUMPKIN_PRICE: u64 = 40;
|
|
73
|
+
const PLOT_PRICE: u64 = 200;
|
|
74
|
+
|
|
75
|
+
const SEASON_BONUS_PCT: u64 = 200;
|
|
76
|
+
const CROW_DAMAGE_PCT: u8 = 30;
|
|
77
|
+
|
|
78
|
+
// ─── Test helpers ─────────────────────────────────────────────────────────────
|
|
79
|
+
|
|
80
|
+
fun setup_dapp(ctx: &mut TxContext): DappStorage {
|
|
81
|
+
let mut ds = init_test::create_dapp_storage_for_testing(ctx);
|
|
82
|
+
deploy_hook::run(&mut ds, ctx);
|
|
83
|
+
ds
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/// Create a UserStorage pre-configured as a registered player.
|
|
87
|
+
/// Uses ctx.sender() as canonical_owner so set_record calls pass the
|
|
88
|
+
/// is_write_authorized check (sender == canonical_owner).
|
|
89
|
+
/// Sets profile (total_earned=0, plots_owned=3) and the requested gold.
|
|
90
|
+
fun setup_player(gold_amount: u64, ctx: &mut TxContext): UserStorage {
|
|
91
|
+
let owner = ctx.sender();
|
|
92
|
+
let mut us = init_test::create_user_storage_for_testing(owner, ctx);
|
|
93
|
+
gold::set(&mut us, gold_amount, ctx);
|
|
94
|
+
profile::set(&mut us, 0, 3, ctx);
|
|
95
|
+
us
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
fun give_crop(us: &mut UserStorage, crop_type: u8, amount: u64, ctx: &mut TxContext) {
|
|
99
|
+
if (crop_type == CROP_WHEAT) { wheat::add(us, amount, ctx) }
|
|
100
|
+
else if (crop_type == CROP_CORN) { corn::add(us, amount, ctx) }
|
|
101
|
+
else if (crop_type == CROP_CARROT) { carrot::add(us, amount, ctx) }
|
|
102
|
+
else { pumpkin::add(us, amount, ctx) };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/// Give seeds (the separate seed resource used for planting).
|
|
106
|
+
fun give_seed(us: &mut UserStorage, crop_type: u8, amount: u64, ctx: &mut TxContext) {
|
|
107
|
+
if (crop_type == CROP_WHEAT) { wheat_seed::add(us, amount, ctx) }
|
|
108
|
+
else if (crop_type == CROP_CORN) { corn_seed::add(us, amount, ctx) }
|
|
109
|
+
else if (crop_type == CROP_CARROT) { carrot_seed::add(us, amount, ctx) }
|
|
110
|
+
else { pumpkin_seed::add(us, amount, ctx) };
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/// Plant a crop, advance the clock to harvest_at + extra_ms, and return the clock.
|
|
114
|
+
/// Caller must call clock::destroy_for_testing when done.
|
|
115
|
+
fun plant_then_advance(
|
|
116
|
+
ds: &DappStorage,
|
|
117
|
+
us: &mut UserStorage,
|
|
118
|
+
plot_id: u8,
|
|
119
|
+
crop_type: u8,
|
|
120
|
+
extra_ms: u64,
|
|
121
|
+
ctx: &mut TxContext,
|
|
122
|
+
): clock::Clock {
|
|
123
|
+
let mut clk = clock::create_for_testing(ctx);
|
|
124
|
+
clock::set_for_testing(&mut clk, 1000);
|
|
125
|
+
farm_system::plant(ds, us, plot_id, crop_type, &clk, ctx);
|
|
126
|
+
let harvest_at = farm_plot::get_harvest_at(us, plot_id);
|
|
127
|
+
clock::set_for_testing(&mut clk, harvest_at + extra_ms);
|
|
128
|
+
clk
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// ═════════════════════════════════════════════════════════════════════════════
|
|
132
|
+
// farm_system::plant
|
|
133
|
+
// ═════════════════════════════════════════════════════════════════════════════
|
|
134
|
+
|
|
135
|
+
// ── success cases ─────────────────────────────────────────────────────────────
|
|
136
|
+
|
|
137
|
+
#[test]
|
|
138
|
+
fun test_plant_wheat_deducts_one_seed_stores_yield() {
|
|
139
|
+
let mut ctx = sui::tx_context::dummy();
|
|
140
|
+
let ds = setup_dapp(&mut ctx);
|
|
141
|
+
let mut us = setup_player(100, &mut ctx);
|
|
142
|
+
give_seed(&mut us, CROP_WHEAT, 5, &mut ctx);
|
|
143
|
+
|
|
144
|
+
let mut clk = clock::create_for_testing(&mut ctx);
|
|
145
|
+
clock::set_for_testing(&mut clk, 1000);
|
|
146
|
+
farm_system::plant(&ds, &mut us, 0, CROP_WHEAT, &clk, &mut ctx);
|
|
147
|
+
|
|
148
|
+
assert!(wheat_seed::get(&us) == 4, 0); // 5 - 1 seed deducted
|
|
149
|
+
assert!(farm_plot::get_count(&us, 0) == WHEAT_YIELD, 1); // stored yield = 6
|
|
150
|
+
assert!(farm_plot::get_crop_type(&us, 0) == CROP_WHEAT, 2);
|
|
151
|
+
let planted_at = farm_plot::get_planted_at(&us, 0);
|
|
152
|
+
assert!(farm_plot::get_harvest_at(&us, 0) == planted_at + WHEAT_MS, 3);
|
|
153
|
+
|
|
154
|
+
clock::destroy_for_testing(clk);
|
|
155
|
+
std::unit_test::destroy(ds);
|
|
156
|
+
std::unit_test::destroy(us);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
#[test]
|
|
160
|
+
fun test_plant_corn_deducts_one_seed_stores_yield() {
|
|
161
|
+
let mut ctx = sui::tx_context::dummy();
|
|
162
|
+
let ds = setup_dapp(&mut ctx);
|
|
163
|
+
let mut us = setup_player(100, &mut ctx);
|
|
164
|
+
give_seed(&mut us, CROP_CORN, 3, &mut ctx);
|
|
165
|
+
|
|
166
|
+
let mut clk = clock::create_for_testing(&mut ctx);
|
|
167
|
+
clock::set_for_testing(&mut clk, 1000);
|
|
168
|
+
farm_system::plant(&ds, &mut us, 0, CROP_CORN, &clk, &mut ctx);
|
|
169
|
+
|
|
170
|
+
assert!(corn_seed::get(&us) == 2, 0);
|
|
171
|
+
assert!(farm_plot::get_count(&us, 0) == CORN_YIELD, 1);
|
|
172
|
+
let planted_at = farm_plot::get_planted_at(&us, 0);
|
|
173
|
+
assert!(farm_plot::get_harvest_at(&us, 0) == planted_at + CORN_MS, 2);
|
|
174
|
+
|
|
175
|
+
clock::destroy_for_testing(clk);
|
|
176
|
+
std::unit_test::destroy(ds);
|
|
177
|
+
std::unit_test::destroy(us);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
#[test]
|
|
181
|
+
fun test_plant_carrot_deducts_one_seed_stores_yield() {
|
|
182
|
+
let mut ctx = sui::tx_context::dummy();
|
|
183
|
+
let ds = setup_dapp(&mut ctx);
|
|
184
|
+
let mut us = setup_player(100, &mut ctx);
|
|
185
|
+
give_seed(&mut us, CROP_CARROT, 2, &mut ctx);
|
|
186
|
+
|
|
187
|
+
let mut clk = clock::create_for_testing(&mut ctx);
|
|
188
|
+
clock::set_for_testing(&mut clk, 1000);
|
|
189
|
+
farm_system::plant(&ds, &mut us, 0, CROP_CARROT, &clk, &mut ctx);
|
|
190
|
+
|
|
191
|
+
assert!(carrot_seed::get(&us) == 1, 0);
|
|
192
|
+
assert!(farm_plot::get_count(&us, 0) == CARROT_YIELD, 1);
|
|
193
|
+
let planted_at = farm_plot::get_planted_at(&us, 0);
|
|
194
|
+
assert!(farm_plot::get_harvest_at(&us, 0) == planted_at + CARROT_MS, 2);
|
|
195
|
+
|
|
196
|
+
clock::destroy_for_testing(clk);
|
|
197
|
+
std::unit_test::destroy(ds);
|
|
198
|
+
std::unit_test::destroy(us);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
#[test]
|
|
202
|
+
fun test_plant_pumpkin_deducts_one_seed_stores_yield() {
|
|
203
|
+
let mut ctx = sui::tx_context::dummy();
|
|
204
|
+
let ds = setup_dapp(&mut ctx);
|
|
205
|
+
let mut us = setup_player(100, &mut ctx);
|
|
206
|
+
give_seed(&mut us, CROP_PUMPKIN, 1, &mut ctx);
|
|
207
|
+
|
|
208
|
+
let mut clk = clock::create_for_testing(&mut ctx);
|
|
209
|
+
clock::set_for_testing(&mut clk, 1000);
|
|
210
|
+
farm_system::plant(&ds, &mut us, 0, CROP_PUMPKIN, &clk, &mut ctx);
|
|
211
|
+
|
|
212
|
+
assert!(!pumpkin_seed::has(&us) || pumpkin_seed::get(&us) == 0, 0);
|
|
213
|
+
assert!(farm_plot::get_count(&us, 0) == PUMPKIN_YIELD, 1);
|
|
214
|
+
let planted_at = farm_plot::get_planted_at(&us, 0);
|
|
215
|
+
assert!(farm_plot::get_harvest_at(&us, 0) == planted_at + PUMPKIN_MS, 2);
|
|
216
|
+
|
|
217
|
+
clock::destroy_for_testing(clk);
|
|
218
|
+
std::unit_test::destroy(ds);
|
|
219
|
+
std::unit_test::destroy(us);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
#[test]
|
|
223
|
+
fun test_plant_three_different_crops_on_three_plots() {
|
|
224
|
+
let mut ctx = sui::tx_context::dummy();
|
|
225
|
+
let ds = setup_dapp(&mut ctx);
|
|
226
|
+
let mut us = setup_player(100, &mut ctx);
|
|
227
|
+
give_seed(&mut us, CROP_WHEAT, 1, &mut ctx);
|
|
228
|
+
give_seed(&mut us, CROP_CORN, 1, &mut ctx);
|
|
229
|
+
give_seed(&mut us, CROP_CARROT, 1, &mut ctx);
|
|
230
|
+
|
|
231
|
+
let mut clk = clock::create_for_testing(&mut ctx);
|
|
232
|
+
clock::set_for_testing(&mut clk, 1000);
|
|
233
|
+
farm_system::plant(&ds, &mut us, 0, CROP_WHEAT, &clk, &mut ctx);
|
|
234
|
+
farm_system::plant(&ds, &mut us, 1, CROP_CORN, &clk, &mut ctx);
|
|
235
|
+
farm_system::plant(&ds, &mut us, 2, CROP_CARROT, &clk, &mut ctx);
|
|
236
|
+
|
|
237
|
+
assert!(farm_plot::get_crop_type(&us, 0) == CROP_WHEAT, 0);
|
|
238
|
+
assert!(farm_plot::get_crop_type(&us, 1) == CROP_CORN, 1);
|
|
239
|
+
assert!(farm_plot::get_crop_type(&us, 2) == CROP_CARROT, 2);
|
|
240
|
+
assert!(farm_plot::get_count(&us, 0) == WHEAT_YIELD, 3);
|
|
241
|
+
assert!(farm_plot::get_count(&us, 1) == CORN_YIELD, 4);
|
|
242
|
+
assert!(farm_plot::get_count(&us, 2) == CARROT_YIELD, 5);
|
|
243
|
+
|
|
244
|
+
clock::destroy_for_testing(clk);
|
|
245
|
+
std::unit_test::destroy(ds);
|
|
246
|
+
std::unit_test::destroy(us);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
#[test]
|
|
250
|
+
fun test_plant_plot_2_boundary_last_owned_plot() {
|
|
251
|
+
let mut ctx = sui::tx_context::dummy();
|
|
252
|
+
let ds = setup_dapp(&mut ctx);
|
|
253
|
+
let mut us = setup_player(100, &mut ctx); // plots_owned = 3 → indices 0,1,2
|
|
254
|
+
give_seed(&mut us, CROP_WHEAT, 1, &mut ctx);
|
|
255
|
+
|
|
256
|
+
let mut clk = clock::create_for_testing(&mut ctx);
|
|
257
|
+
clock::set_for_testing(&mut clk, 1000);
|
|
258
|
+
farm_system::plant(&ds, &mut us, 2, CROP_WHEAT, &clk, &mut ctx); // index 2 is valid
|
|
259
|
+
|
|
260
|
+
assert!(farm_plot::get_crop_type(&us, 2) == CROP_WHEAT, 0);
|
|
261
|
+
|
|
262
|
+
clock::destroy_for_testing(clk);
|
|
263
|
+
std::unit_test::destroy(ds);
|
|
264
|
+
std::unit_test::destroy(us);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// ── failure cases ─────────────────────────────────────────────────────────────
|
|
268
|
+
|
|
269
|
+
#[test]
|
|
270
|
+
#[expected_failure]
|
|
271
|
+
fun test_plant_fails_not_registered() {
|
|
272
|
+
let mut ctx = sui::tx_context::dummy();
|
|
273
|
+
let ds = setup_dapp(&mut ctx);
|
|
274
|
+
let mut us = init_test::create_user_storage_for_testing(ctx.sender(), &mut ctx); // no profile
|
|
275
|
+
let clk = clock::create_for_testing(&mut ctx);
|
|
276
|
+
|
|
277
|
+
farm_system::plant(&ds, &mut us, 0, CROP_WHEAT, &clk, &mut ctx);
|
|
278
|
+
|
|
279
|
+
clock::destroy_for_testing(clk);
|
|
280
|
+
std::unit_test::destroy(ds);
|
|
281
|
+
std::unit_test::destroy(us);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
#[test]
|
|
285
|
+
#[expected_failure]
|
|
286
|
+
fun test_plant_fails_crop_type_none() {
|
|
287
|
+
let mut ctx = sui::tx_context::dummy();
|
|
288
|
+
let ds = setup_dapp(&mut ctx);
|
|
289
|
+
let mut us = setup_player(100, &mut ctx);
|
|
290
|
+
let clk = clock::create_for_testing(&mut ctx);
|
|
291
|
+
|
|
292
|
+
farm_system::plant(&ds, &mut us, 0, 0, &clk, &mut ctx); // 0 = CROP_NONE
|
|
293
|
+
|
|
294
|
+
clock::destroy_for_testing(clk);
|
|
295
|
+
std::unit_test::destroy(ds);
|
|
296
|
+
std::unit_test::destroy(us);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
#[test]
|
|
300
|
+
#[expected_failure]
|
|
301
|
+
fun test_plant_fails_crop_type_out_of_range() {
|
|
302
|
+
let mut ctx = sui::tx_context::dummy();
|
|
303
|
+
let ds = setup_dapp(&mut ctx);
|
|
304
|
+
let mut us = setup_player(100, &mut ctx);
|
|
305
|
+
let clk = clock::create_for_testing(&mut ctx);
|
|
306
|
+
|
|
307
|
+
farm_system::plant(&ds, &mut us, 0, 5, &clk, &mut ctx); // no crop type 5
|
|
308
|
+
|
|
309
|
+
clock::destroy_for_testing(clk);
|
|
310
|
+
std::unit_test::destroy(ds);
|
|
311
|
+
std::unit_test::destroy(us);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
#[test]
|
|
315
|
+
#[expected_failure]
|
|
316
|
+
fun test_plant_fails_plot_not_owned() {
|
|
317
|
+
let mut ctx = sui::tx_context::dummy();
|
|
318
|
+
let ds = setup_dapp(&mut ctx);
|
|
319
|
+
let mut us = setup_player(100, &mut ctx); // plots_owned = 3 → valid: 0,1,2
|
|
320
|
+
give_seed(&mut us, CROP_WHEAT, 1, &mut ctx);
|
|
321
|
+
let clk = clock::create_for_testing(&mut ctx);
|
|
322
|
+
|
|
323
|
+
farm_system::plant(&ds, &mut us, 3, CROP_WHEAT, &clk, &mut ctx); // index 3 not owned
|
|
324
|
+
|
|
325
|
+
clock::destroy_for_testing(clk);
|
|
326
|
+
std::unit_test::destroy(ds);
|
|
327
|
+
std::unit_test::destroy(us);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
#[test]
|
|
331
|
+
#[expected_failure]
|
|
332
|
+
fun test_plant_fails_plot_already_has_crop() {
|
|
333
|
+
let mut ctx = sui::tx_context::dummy();
|
|
334
|
+
let ds = setup_dapp(&mut ctx);
|
|
335
|
+
let mut us = setup_player(100, &mut ctx);
|
|
336
|
+
give_seed(&mut us, CROP_WHEAT, 3, &mut ctx);
|
|
337
|
+
let mut clk = clock::create_for_testing(&mut ctx);
|
|
338
|
+
clock::set_for_testing(&mut clk, 1000);
|
|
339
|
+
|
|
340
|
+
farm_system::plant(&ds, &mut us, 0, CROP_WHEAT, &clk, &mut ctx);
|
|
341
|
+
farm_system::plant(&ds, &mut us, 0, CROP_WHEAT, &clk, &mut ctx); // second plant aborts
|
|
342
|
+
|
|
343
|
+
clock::destroy_for_testing(clk);
|
|
344
|
+
std::unit_test::destroy(ds);
|
|
345
|
+
std::unit_test::destroy(us);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
#[test]
|
|
349
|
+
#[expected_failure]
|
|
350
|
+
fun test_plant_fails_no_seeds_in_inventory() {
|
|
351
|
+
let mut ctx = sui::tx_context::dummy();
|
|
352
|
+
let ds = setup_dapp(&mut ctx);
|
|
353
|
+
let mut us = setup_player(100, &mut ctx); // zero wheat
|
|
354
|
+
let clk = clock::create_for_testing(&mut ctx);
|
|
355
|
+
|
|
356
|
+
farm_system::plant(&ds, &mut us, 0, CROP_WHEAT, &clk, &mut ctx);
|
|
357
|
+
|
|
358
|
+
clock::destroy_for_testing(clk);
|
|
359
|
+
std::unit_test::destroy(ds);
|
|
360
|
+
std::unit_test::destroy(us);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// ═════════════════════════════════════════════════════════════════════════════
|
|
364
|
+
// farm_system::harvest
|
|
365
|
+
// ═════════════════════════════════════════════════════════════════════════════
|
|
366
|
+
|
|
367
|
+
// ── success cases ─────────────────────────────────────────────────────────────
|
|
368
|
+
|
|
369
|
+
#[test]
|
|
370
|
+
fun test_harvest_wheat_base_yield_no_bonus() {
|
|
371
|
+
let mut ctx = sui::tx_context::dummy();
|
|
372
|
+
let ds = setup_dapp(&mut ctx);
|
|
373
|
+
let mut us = setup_player(100, &mut ctx);
|
|
374
|
+
give_seed(&mut us, CROP_WHEAT, 1, &mut ctx);
|
|
375
|
+
|
|
376
|
+
let clk = plant_then_advance(&ds, &mut us, 0, CROP_WHEAT, 0, &mut ctx);
|
|
377
|
+
farm_system::harvest(&ds, &mut us, 0, &clk, &mut ctx);
|
|
378
|
+
|
|
379
|
+
assert!(wheat::get(&us) == WHEAT_YIELD, 0); // base 6
|
|
380
|
+
assert!(farm_plot::get_crop_type(&us, 0) == 0, 1); // plot cleared
|
|
381
|
+
assert!(farm_plot::get_count(&us, 0) == 0, 2);
|
|
382
|
+
assert!(profile::get_total_earned(&us) == WHEAT_YIELD * WHEAT_SELL, 3); // 48
|
|
383
|
+
|
|
384
|
+
clock::destroy_for_testing(clk);
|
|
385
|
+
std::unit_test::destroy(ds);
|
|
386
|
+
std::unit_test::destroy(us);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
#[test]
|
|
390
|
+
fun test_harvest_corn_base_yield_no_bonus() {
|
|
391
|
+
let mut ctx = sui::tx_context::dummy();
|
|
392
|
+
let ds = setup_dapp(&mut ctx);
|
|
393
|
+
let mut us = setup_player(100, &mut ctx);
|
|
394
|
+
give_seed(&mut us, CROP_CORN, 1, &mut ctx);
|
|
395
|
+
|
|
396
|
+
let clk = plant_then_advance(&ds, &mut us, 0, CROP_CORN, 0, &mut ctx);
|
|
397
|
+
farm_system::harvest(&ds, &mut us, 0, &clk, &mut ctx);
|
|
398
|
+
|
|
399
|
+
assert!(corn::get(&us) == CORN_YIELD, 0);
|
|
400
|
+
assert!(profile::get_total_earned(&us) == CORN_YIELD * CORN_SELL, 1); // 140
|
|
401
|
+
|
|
402
|
+
clock::destroy_for_testing(clk);
|
|
403
|
+
std::unit_test::destroy(ds);
|
|
404
|
+
std::unit_test::destroy(us);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
#[test]
|
|
408
|
+
fun test_harvest_carrot_base_yield_no_bonus() {
|
|
409
|
+
let mut ctx = sui::tx_context::dummy();
|
|
410
|
+
let ds = setup_dapp(&mut ctx);
|
|
411
|
+
let mut us = setup_player(100, &mut ctx);
|
|
412
|
+
give_seed(&mut us, CROP_CARROT, 1, &mut ctx);
|
|
413
|
+
|
|
414
|
+
let clk = plant_then_advance(&ds, &mut us, 0, CROP_CARROT, 0, &mut ctx);
|
|
415
|
+
farm_system::harvest(&ds, &mut us, 0, &clk, &mut ctx);
|
|
416
|
+
|
|
417
|
+
assert!(carrot::get(&us) == CARROT_YIELD, 0);
|
|
418
|
+
assert!(profile::get_total_earned(&us) == CARROT_YIELD * CARROT_SELL, 1); // 360
|
|
419
|
+
|
|
420
|
+
clock::destroy_for_testing(clk);
|
|
421
|
+
std::unit_test::destroy(ds);
|
|
422
|
+
std::unit_test::destroy(us);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
#[test]
|
|
426
|
+
fun test_harvest_pumpkin_base_yield_no_bonus() {
|
|
427
|
+
let mut ctx = sui::tx_context::dummy();
|
|
428
|
+
let ds = setup_dapp(&mut ctx);
|
|
429
|
+
let mut us = setup_player(100, &mut ctx);
|
|
430
|
+
give_seed(&mut us, CROP_PUMPKIN, 1, &mut ctx);
|
|
431
|
+
|
|
432
|
+
let clk = plant_then_advance(&ds, &mut us, 0, CROP_PUMPKIN, 0, &mut ctx);
|
|
433
|
+
farm_system::harvest(&ds, &mut us, 0, &clk, &mut ctx);
|
|
434
|
+
|
|
435
|
+
assert!(pumpkin::get(&us) == PUMPKIN_YIELD, 0);
|
|
436
|
+
assert!(profile::get_total_earned(&us) == PUMPKIN_YIELD * PUMPKIN_SELL, 1); // 300
|
|
437
|
+
|
|
438
|
+
clock::destroy_for_testing(clk);
|
|
439
|
+
std::unit_test::destroy(ds);
|
|
440
|
+
std::unit_test::destroy(us);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
#[test]
|
|
444
|
+
fun test_harvest_succeeds_exactly_at_harvest_at() {
|
|
445
|
+
let mut ctx = sui::tx_context::dummy();
|
|
446
|
+
let ds = setup_dapp(&mut ctx);
|
|
447
|
+
let mut us = setup_player(100, &mut ctx);
|
|
448
|
+
give_seed(&mut us, CROP_WHEAT, 1, &mut ctx);
|
|
449
|
+
|
|
450
|
+
// plant_then_advance with extra_ms=0 sets clock to exactly harvest_at
|
|
451
|
+
let clk = plant_then_advance(&ds, &mut us, 0, CROP_WHEAT, 0, &mut ctx);
|
|
452
|
+
farm_system::harvest(&ds, &mut us, 0, &clk, &mut ctx);
|
|
453
|
+
|
|
454
|
+
assert!(wheat::get(&us) == WHEAT_YIELD, 0);
|
|
455
|
+
|
|
456
|
+
clock::destroy_for_testing(clk);
|
|
457
|
+
std::unit_test::destroy(ds);
|
|
458
|
+
std::unit_test::destroy(us);
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
#[test]
|
|
462
|
+
fun test_harvest_season_bonus_doubles_matching_crop() {
|
|
463
|
+
let mut ctx = sui::tx_context::dummy();
|
|
464
|
+
let mut ds = setup_dapp(&mut ctx);
|
|
465
|
+
let mut us = setup_player(100, &mut ctx);
|
|
466
|
+
give_seed(&mut us, CROP_WHEAT, 1, &mut ctx);
|
|
467
|
+
|
|
468
|
+
let mut clk = clock::create_for_testing(&mut ctx);
|
|
469
|
+
clock::set_for_testing(&mut clk, 1000);
|
|
470
|
+
farm_system::plant(&ds, &mut us, 0, CROP_WHEAT, &clk, &mut ctx);
|
|
471
|
+
|
|
472
|
+
let harvest_at = farm_plot::get_harvest_at(&us, 0);
|
|
473
|
+
// Active season: bonus_crop = WHEAT, end far in future
|
|
474
|
+
season_config::set(&mut ds, 1, harvest_at + 1_000_000, CROP_WHEAT);
|
|
475
|
+
clock::set_for_testing(&mut clk, harvest_at);
|
|
476
|
+
|
|
477
|
+
farm_system::harvest(&ds, &mut us, 0, &clk, &mut ctx);
|
|
478
|
+
|
|
479
|
+
// after_bonus = WHEAT_YIELD * SEASON_BONUS_PCT / 100 = 6 * 200 / 100 = 12
|
|
480
|
+
assert!(wheat::get(&us) == WHEAT_YIELD * SEASON_BONUS_PCT / 100, 0); // 12
|
|
481
|
+
|
|
482
|
+
clock::destroy_for_testing(clk);
|
|
483
|
+
std::unit_test::destroy(ds);
|
|
484
|
+
std::unit_test::destroy(us);
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
#[test]
|
|
488
|
+
fun test_harvest_season_bonus_no_effect_on_non_matching_crop() {
|
|
489
|
+
let mut ctx = sui::tx_context::dummy();
|
|
490
|
+
let mut ds = setup_dapp(&mut ctx);
|
|
491
|
+
let mut us = setup_player(100, &mut ctx);
|
|
492
|
+
give_seed(&mut us, CROP_WHEAT, 1, &mut ctx);
|
|
493
|
+
|
|
494
|
+
let mut clk = clock::create_for_testing(&mut ctx);
|
|
495
|
+
clock::set_for_testing(&mut clk, 1000);
|
|
496
|
+
farm_system::plant(&ds, &mut us, 0, CROP_WHEAT, &clk, &mut ctx);
|
|
497
|
+
|
|
498
|
+
let harvest_at = farm_plot::get_harvest_at(&us, 0);
|
|
499
|
+
// Season active but bonus is CORN, not WHEAT
|
|
500
|
+
season_config::set(&mut ds, 1, harvest_at + 1_000_000, CROP_CORN);
|
|
501
|
+
clock::set_for_testing(&mut clk, harvest_at);
|
|
502
|
+
|
|
503
|
+
farm_system::harvest(&ds, &mut us, 0, &clk, &mut ctx);
|
|
504
|
+
|
|
505
|
+
assert!(wheat::get(&us) == WHEAT_YIELD, 0); // no boost
|
|
506
|
+
|
|
507
|
+
clock::destroy_for_testing(clk);
|
|
508
|
+
std::unit_test::destroy(ds);
|
|
509
|
+
std::unit_test::destroy(us);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
#[test]
|
|
513
|
+
fun test_harvest_expired_season_no_boost() {
|
|
514
|
+
let mut ctx = sui::tx_context::dummy();
|
|
515
|
+
let mut ds = setup_dapp(&mut ctx);
|
|
516
|
+
let mut us = setup_player(100, &mut ctx);
|
|
517
|
+
give_seed(&mut us, CROP_WHEAT, 1, &mut ctx);
|
|
518
|
+
|
|
519
|
+
let mut clk = clock::create_for_testing(&mut ctx);
|
|
520
|
+
clock::set_for_testing(&mut clk, 1000);
|
|
521
|
+
farm_system::plant(&ds, &mut us, 0, CROP_WHEAT, &clk, &mut ctx);
|
|
522
|
+
|
|
523
|
+
let harvest_at = farm_plot::get_harvest_at(&us, 0);
|
|
524
|
+
// Season already ended 1 ms before harvest
|
|
525
|
+
season_config::set(&mut ds, 1, harvest_at - 1, CROP_WHEAT);
|
|
526
|
+
clock::set_for_testing(&mut clk, harvest_at);
|
|
527
|
+
|
|
528
|
+
farm_system::harvest(&ds, &mut us, 0, &clk, &mut ctx);
|
|
529
|
+
|
|
530
|
+
assert!(wheat::get(&us) == WHEAT_YIELD, 0); // no boost (now >= season_end)
|
|
531
|
+
|
|
532
|
+
clock::destroy_for_testing(clk);
|
|
533
|
+
std::unit_test::destroy(ds);
|
|
534
|
+
std::unit_test::destroy(us);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
#[test]
|
|
538
|
+
fun test_harvest_crow_damage_active_reduces_yield() {
|
|
539
|
+
let mut ctx = sui::tx_context::dummy();
|
|
540
|
+
let ds = setup_dapp(&mut ctx);
|
|
541
|
+
let mut us = setup_player(100, &mut ctx);
|
|
542
|
+
give_seed(&mut us, CROP_WHEAT, 1, &mut ctx);
|
|
543
|
+
|
|
544
|
+
let mut clk = clock::create_for_testing(&mut ctx);
|
|
545
|
+
clock::set_for_testing(&mut clk, 1000);
|
|
546
|
+
farm_system::plant(&ds, &mut us, 0, CROP_WHEAT, &clk, &mut ctx);
|
|
547
|
+
|
|
548
|
+
let harvest_at = farm_plot::get_harvest_at(&us, 0);
|
|
549
|
+
// Crow damage 30%, expires after harvest_at
|
|
550
|
+
crow_damage::set(&mut us, harvest_at + 100_000, CROW_DAMAGE_PCT, &mut ctx);
|
|
551
|
+
clock::set_for_testing(&mut clk, harvest_at);
|
|
552
|
+
|
|
553
|
+
farm_system::harvest(&ds, &mut us, 0, &clk, &mut ctx);
|
|
554
|
+
|
|
555
|
+
// final = 6 * (100 - 30) / 100 = 6 * 70 / 100 = 4
|
|
556
|
+
assert!(wheat::get(&us) == 4, 0);
|
|
557
|
+
|
|
558
|
+
clock::destroy_for_testing(clk);
|
|
559
|
+
std::unit_test::destroy(ds);
|
|
560
|
+
std::unit_test::destroy(us);
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
#[test]
|
|
564
|
+
fun test_harvest_crow_damage_expired_no_penalty() {
|
|
565
|
+
let mut ctx = sui::tx_context::dummy();
|
|
566
|
+
let ds = setup_dapp(&mut ctx);
|
|
567
|
+
let mut us = setup_player(100, &mut ctx);
|
|
568
|
+
give_seed(&mut us, CROP_WHEAT, 1, &mut ctx);
|
|
569
|
+
|
|
570
|
+
let mut clk = clock::create_for_testing(&mut ctx);
|
|
571
|
+
clock::set_for_testing(&mut clk, 1000);
|
|
572
|
+
farm_system::plant(&ds, &mut us, 0, CROP_WHEAT, &clk, &mut ctx);
|
|
573
|
+
|
|
574
|
+
let harvest_at = farm_plot::get_harvest_at(&us, 0);
|
|
575
|
+
// Crow damage already expired 1 ms before harvest
|
|
576
|
+
crow_damage::set(&mut us, harvest_at - 1, CROW_DAMAGE_PCT, &mut ctx);
|
|
577
|
+
clock::set_for_testing(&mut clk, harvest_at);
|
|
578
|
+
|
|
579
|
+
farm_system::harvest(&ds, &mut us, 0, &clk, &mut ctx);
|
|
580
|
+
|
|
581
|
+
assert!(wheat::get(&us) == WHEAT_YIELD, 0); // full yield, debuff expired
|
|
582
|
+
|
|
583
|
+
clock::destroy_for_testing(clk);
|
|
584
|
+
std::unit_test::destroy(ds);
|
|
585
|
+
std::unit_test::destroy(us);
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
#[test]
|
|
589
|
+
fun test_harvest_season_bonus_and_crow_damage_combined() {
|
|
590
|
+
let mut ctx = sui::tx_context::dummy();
|
|
591
|
+
let mut ds = setup_dapp(&mut ctx);
|
|
592
|
+
let mut us = setup_player(100, &mut ctx);
|
|
593
|
+
give_seed(&mut us, CROP_WHEAT, 1, &mut ctx);
|
|
594
|
+
|
|
595
|
+
let mut clk = clock::create_for_testing(&mut ctx);
|
|
596
|
+
clock::set_for_testing(&mut clk, 1000);
|
|
597
|
+
farm_system::plant(&ds, &mut us, 0, CROP_WHEAT, &clk, &mut ctx);
|
|
598
|
+
|
|
599
|
+
let harvest_at = farm_plot::get_harvest_at(&us, 0);
|
|
600
|
+
season_config::set(&mut ds, 1, harvest_at + 1_000_000, CROP_WHEAT); // 2× bonus
|
|
601
|
+
crow_damage::set(&mut us, harvest_at + 1_000_000, CROW_DAMAGE_PCT, &mut ctx); // −30%
|
|
602
|
+
clock::set_for_testing(&mut clk, harvest_at);
|
|
603
|
+
|
|
604
|
+
farm_system::harvest(&ds, &mut us, 0, &clk, &mut ctx);
|
|
605
|
+
|
|
606
|
+
// after_bonus = 6 * 200 / 100 = 12; final = 12 * 70 / 100 = 8
|
|
607
|
+
assert!(wheat::get(&us) == 8, 0);
|
|
608
|
+
|
|
609
|
+
clock::destroy_for_testing(clk);
|
|
610
|
+
std::unit_test::destroy(ds);
|
|
611
|
+
std::unit_test::destroy(us);
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
#[test]
|
|
615
|
+
fun test_harvest_accumulates_total_earned_over_two_plots() {
|
|
616
|
+
let mut ctx = sui::tx_context::dummy();
|
|
617
|
+
let ds = setup_dapp(&mut ctx);
|
|
618
|
+
let mut us = setup_player(100, &mut ctx);
|
|
619
|
+
give_seed(&mut us, CROP_WHEAT, 2, &mut ctx);
|
|
620
|
+
|
|
621
|
+
let mut clk = clock::create_for_testing(&mut ctx);
|
|
622
|
+
clock::set_for_testing(&mut clk, 1000);
|
|
623
|
+
farm_system::plant(&ds, &mut us, 0, CROP_WHEAT, &clk, &mut ctx);
|
|
624
|
+
farm_system::plant(&ds, &mut us, 1, CROP_WHEAT, &clk, &mut ctx);
|
|
625
|
+
|
|
626
|
+
let harvest_at = farm_plot::get_harvest_at(&us, 0);
|
|
627
|
+
clock::set_for_testing(&mut clk, harvest_at);
|
|
628
|
+
farm_system::harvest(&ds, &mut us, 0, &clk, &mut ctx);
|
|
629
|
+
farm_system::harvest(&ds, &mut us, 1, &clk, &mut ctx);
|
|
630
|
+
|
|
631
|
+
// total_earned = 2 × (WHEAT_YIELD × WHEAT_SELL) = 2 × 48 = 96
|
|
632
|
+
assert!(profile::get_total_earned(&us) == 2 * WHEAT_YIELD * WHEAT_SELL, 0);
|
|
633
|
+
|
|
634
|
+
clock::destroy_for_testing(clk);
|
|
635
|
+
std::unit_test::destroy(ds);
|
|
636
|
+
std::unit_test::destroy(us);
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
#[test]
|
|
640
|
+
fun test_harvest_season_stats_accumulated_correctly() {
|
|
641
|
+
let mut ctx = sui::tx_context::dummy();
|
|
642
|
+
let ds = setup_dapp(&mut ctx);
|
|
643
|
+
let mut us = setup_player(100, &mut ctx);
|
|
644
|
+
give_seed(&mut us, CROP_CORN, 1, &mut ctx);
|
|
645
|
+
|
|
646
|
+
let clk = plant_then_advance(&ds, &mut us, 0, CROP_CORN, 0, &mut ctx);
|
|
647
|
+
farm_system::harvest(&ds, &mut us, 0, &clk, &mut ctx);
|
|
648
|
+
|
|
649
|
+
assert!(season_stats::has(&us), 0);
|
|
650
|
+
assert!(season_stats::get(&us) == CORN_YIELD * CORN_SELL, 1); // 140
|
|
651
|
+
|
|
652
|
+
clock::destroy_for_testing(clk);
|
|
653
|
+
std::unit_test::destroy(ds);
|
|
654
|
+
std::unit_test::destroy(us);
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
#[test]
|
|
658
|
+
fun test_harvest_then_replant_same_plot_succeeds() {
|
|
659
|
+
let mut ctx = sui::tx_context::dummy();
|
|
660
|
+
let ds = setup_dapp(&mut ctx);
|
|
661
|
+
let mut us = setup_player(100, &mut ctx);
|
|
662
|
+
give_seed(&mut us, CROP_WHEAT, 2, &mut ctx); // 2 seeds: 1 for first plant, 1 for replant
|
|
663
|
+
|
|
664
|
+
let mut clk = clock::create_for_testing(&mut ctx);
|
|
665
|
+
clock::set_for_testing(&mut clk, 1000);
|
|
666
|
+
farm_system::plant(&ds, &mut us, 0, CROP_WHEAT, &clk, &mut ctx);
|
|
667
|
+
|
|
668
|
+
let harvest_at = farm_plot::get_harvest_at(&us, 0);
|
|
669
|
+
clock::set_for_testing(&mut clk, harvest_at);
|
|
670
|
+
farm_system::harvest(&ds, &mut us, 0, &clk, &mut ctx);
|
|
671
|
+
|
|
672
|
+
// Re-plant on the same plot using a second seed
|
|
673
|
+
farm_system::plant(&ds, &mut us, 0, CROP_WHEAT, &clk, &mut ctx);
|
|
674
|
+
assert!(farm_plot::get_crop_type(&us, 0) == CROP_WHEAT, 0);
|
|
675
|
+
// Both seeds consumed; harvested crops (WHEAT_YIELD) still intact in crop resource
|
|
676
|
+
assert!(wheat_seed::get(&us) == 0, 1);
|
|
677
|
+
assert!(wheat::get(&us) == WHEAT_YIELD, 2);
|
|
678
|
+
|
|
679
|
+
clock::destroy_for_testing(clk);
|
|
680
|
+
std::unit_test::destroy(ds);
|
|
681
|
+
std::unit_test::destroy(us);
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
// ── failure cases ─────────────────────────────────────────────────────────────
|
|
685
|
+
|
|
686
|
+
#[test]
|
|
687
|
+
#[expected_failure]
|
|
688
|
+
fun test_harvest_fails_not_registered() {
|
|
689
|
+
let mut ctx = sui::tx_context::dummy();
|
|
690
|
+
let ds = setup_dapp(&mut ctx);
|
|
691
|
+
let mut us = init_test::create_user_storage_for_testing(ctx.sender(), &mut ctx);
|
|
692
|
+
let clk = clock::create_for_testing(&mut ctx);
|
|
693
|
+
|
|
694
|
+
farm_system::harvest(&ds, &mut us, 0, &clk, &mut ctx);
|
|
695
|
+
|
|
696
|
+
clock::destroy_for_testing(clk);
|
|
697
|
+
std::unit_test::destroy(ds);
|
|
698
|
+
std::unit_test::destroy(us);
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
#[test]
|
|
702
|
+
#[expected_failure]
|
|
703
|
+
fun test_harvest_fails_plot_record_does_not_exist() {
|
|
704
|
+
let mut ctx = sui::tx_context::dummy();
|
|
705
|
+
let ds = setup_dapp(&mut ctx);
|
|
706
|
+
let mut us = setup_player(100, &mut ctx);
|
|
707
|
+
let clk = clock::create_for_testing(&mut ctx);
|
|
708
|
+
|
|
709
|
+
farm_system::harvest(&ds, &mut us, 0, &clk, &mut ctx); // no plot record set
|
|
710
|
+
|
|
711
|
+
clock::destroy_for_testing(clk);
|
|
712
|
+
std::unit_test::destroy(ds);
|
|
713
|
+
std::unit_test::destroy(us);
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
#[test]
|
|
717
|
+
#[expected_failure]
|
|
718
|
+
fun test_harvest_fails_plot_is_empty_after_previous_harvest() {
|
|
719
|
+
let mut ctx = sui::tx_context::dummy();
|
|
720
|
+
let ds = setup_dapp(&mut ctx);
|
|
721
|
+
let mut us = setup_player(100, &mut ctx);
|
|
722
|
+
give_seed(&mut us, CROP_WHEAT, 1, &mut ctx);
|
|
723
|
+
|
|
724
|
+
let mut clk = clock::create_for_testing(&mut ctx);
|
|
725
|
+
clock::set_for_testing(&mut clk, 1000);
|
|
726
|
+
farm_system::plant(&ds, &mut us, 0, CROP_WHEAT, &clk, &mut ctx);
|
|
727
|
+
|
|
728
|
+
let harvest_at = farm_plot::get_harvest_at(&us, 0);
|
|
729
|
+
clock::set_for_testing(&mut clk, harvest_at);
|
|
730
|
+
farm_system::harvest(&ds, &mut us, 0, &clk, &mut ctx); // first: ok
|
|
731
|
+
farm_system::harvest(&ds, &mut us, 0, &clk, &mut ctx); // second: plot is empty
|
|
732
|
+
|
|
733
|
+
clock::destroy_for_testing(clk);
|
|
734
|
+
std::unit_test::destroy(ds);
|
|
735
|
+
std::unit_test::destroy(us);
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
#[test]
|
|
739
|
+
#[expected_failure]
|
|
740
|
+
fun test_harvest_fails_one_ms_before_ready() {
|
|
741
|
+
let mut ctx = sui::tx_context::dummy();
|
|
742
|
+
let ds = setup_dapp(&mut ctx);
|
|
743
|
+
let mut us = setup_player(100, &mut ctx);
|
|
744
|
+
give_seed(&mut us, CROP_WHEAT, 1, &mut ctx);
|
|
745
|
+
|
|
746
|
+
let mut clk = clock::create_for_testing(&mut ctx);
|
|
747
|
+
clock::set_for_testing(&mut clk, 1000);
|
|
748
|
+
farm_system::plant(&ds, &mut us, 0, CROP_WHEAT, &clk, &mut ctx);
|
|
749
|
+
|
|
750
|
+
let harvest_at = farm_plot::get_harvest_at(&us, 0);
|
|
751
|
+
clock::set_for_testing(&mut clk, harvest_at - 1); // 1 ms too early
|
|
752
|
+
|
|
753
|
+
farm_system::harvest(&ds, &mut us, 0, &clk, &mut ctx);
|
|
754
|
+
|
|
755
|
+
clock::destroy_for_testing(clk);
|
|
756
|
+
std::unit_test::destroy(ds);
|
|
757
|
+
std::unit_test::destroy(us);
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
// ═════════════════════════════════════════════════════════════════════════════
|
|
761
|
+
// shop_system::buy_seeds
|
|
762
|
+
// ═════════════════════════════════════════════════════════════════════════════
|
|
763
|
+
|
|
764
|
+
#[test]
|
|
765
|
+
fun test_buy_seeds_wheat_deducts_gold_adds_inventory() {
|
|
766
|
+
let mut ctx = sui::tx_context::dummy();
|
|
767
|
+
let ds = setup_dapp(&mut ctx);
|
|
768
|
+
let mut us = setup_player(100, &mut ctx);
|
|
769
|
+
|
|
770
|
+
shop_system::buy_seeds(&ds, &mut us, CROP_WHEAT, 3, &mut ctx);
|
|
771
|
+
|
|
772
|
+
assert!(gold::get(&us) == 100 - 3 * WHEAT_PRICE, 0); // 85
|
|
773
|
+
assert!(wheat_seed::get(&us) == 3, 1);
|
|
774
|
+
|
|
775
|
+
std::unit_test::destroy(ds);
|
|
776
|
+
std::unit_test::destroy(us);
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
#[test]
|
|
780
|
+
fun test_buy_seeds_corn_correct_price() {
|
|
781
|
+
let mut ctx = sui::tx_context::dummy();
|
|
782
|
+
let ds = setup_dapp(&mut ctx);
|
|
783
|
+
let mut us = setup_player(100, &mut ctx);
|
|
784
|
+
|
|
785
|
+
shop_system::buy_seeds(&ds, &mut us, CROP_CORN, 2, &mut ctx);
|
|
786
|
+
|
|
787
|
+
assert!(gold::get(&us) == 100 - 2 * CORN_PRICE, 0); // 60
|
|
788
|
+
assert!(corn_seed::get(&us) == 2, 1);
|
|
789
|
+
|
|
790
|
+
std::unit_test::destroy(ds);
|
|
791
|
+
std::unit_test::destroy(us);
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
#[test]
|
|
795
|
+
fun test_buy_seeds_carrot_correct_price() {
|
|
796
|
+
let mut ctx = sui::tx_context::dummy();
|
|
797
|
+
let ds = setup_dapp(&mut ctx);
|
|
798
|
+
let mut us = setup_player(100, &mut ctx);
|
|
799
|
+
|
|
800
|
+
shop_system::buy_seeds(&ds, &mut us, CROP_CARROT, 1, &mut ctx);
|
|
801
|
+
|
|
802
|
+
assert!(gold::get(&us) == 100 - CARROT_PRICE, 0); // 40
|
|
803
|
+
assert!(carrot_seed::get(&us) == 1, 1);
|
|
804
|
+
|
|
805
|
+
std::unit_test::destroy(ds);
|
|
806
|
+
std::unit_test::destroy(us);
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
#[test]
|
|
810
|
+
fun test_buy_seeds_pumpkin_correct_price() {
|
|
811
|
+
let mut ctx = sui::tx_context::dummy();
|
|
812
|
+
let ds = setup_dapp(&mut ctx);
|
|
813
|
+
let mut us = setup_player(200, &mut ctx);
|
|
814
|
+
|
|
815
|
+
shop_system::buy_seeds(&ds, &mut us, CROP_PUMPKIN, 4, &mut ctx);
|
|
816
|
+
|
|
817
|
+
assert!(gold::get(&us) == 200 - 4 * PUMPKIN_PRICE, 0); // 40
|
|
818
|
+
assert!(pumpkin_seed::get(&us) == 4, 1);
|
|
819
|
+
|
|
820
|
+
std::unit_test::destroy(ds);
|
|
821
|
+
std::unit_test::destroy(us);
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
#[test]
|
|
825
|
+
fun test_buy_seeds_exact_gold_boundary() {
|
|
826
|
+
let mut ctx = sui::tx_context::dummy();
|
|
827
|
+
let ds = setup_dapp(&mut ctx);
|
|
828
|
+
let mut us = setup_player(WHEAT_PRICE, &mut ctx); // exactly 5
|
|
829
|
+
|
|
830
|
+
shop_system::buy_seeds(&ds, &mut us, CROP_WHEAT, 1, &mut ctx);
|
|
831
|
+
|
|
832
|
+
assert!(gold::get(&us) == 0, 0);
|
|
833
|
+
assert!(wheat_seed::get(&us) == 1, 1);
|
|
834
|
+
|
|
835
|
+
std::unit_test::destroy(ds);
|
|
836
|
+
std::unit_test::destroy(us);
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
#[test]
|
|
840
|
+
#[expected_failure]
|
|
841
|
+
fun test_buy_seeds_fails_not_registered() {
|
|
842
|
+
let mut ctx = sui::tx_context::dummy();
|
|
843
|
+
let ds = setup_dapp(&mut ctx);
|
|
844
|
+
let mut us = init_test::create_user_storage_for_testing(ctx.sender(), &mut ctx);
|
|
845
|
+
|
|
846
|
+
shop_system::buy_seeds(&ds, &mut us, CROP_WHEAT, 1, &mut ctx);
|
|
847
|
+
|
|
848
|
+
std::unit_test::destroy(ds);
|
|
849
|
+
std::unit_test::destroy(us);
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
#[test]
|
|
853
|
+
#[expected_failure]
|
|
854
|
+
fun test_buy_seeds_fails_crop_type_none() {
|
|
855
|
+
let mut ctx = sui::tx_context::dummy();
|
|
856
|
+
let ds = setup_dapp(&mut ctx);
|
|
857
|
+
let mut us = setup_player(100, &mut ctx);
|
|
858
|
+
|
|
859
|
+
shop_system::buy_seeds(&ds, &mut us, 0, 1, &mut ctx); // type 0 invalid
|
|
860
|
+
|
|
861
|
+
std::unit_test::destroy(ds);
|
|
862
|
+
std::unit_test::destroy(us);
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
#[test]
|
|
866
|
+
#[expected_failure]
|
|
867
|
+
fun test_buy_seeds_fails_crop_type_out_of_range() {
|
|
868
|
+
let mut ctx = sui::tx_context::dummy();
|
|
869
|
+
let ds = setup_dapp(&mut ctx);
|
|
870
|
+
let mut us = setup_player(100, &mut ctx);
|
|
871
|
+
|
|
872
|
+
shop_system::buy_seeds(&ds, &mut us, 5, 1, &mut ctx); // type 5 invalid
|
|
873
|
+
|
|
874
|
+
std::unit_test::destroy(ds);
|
|
875
|
+
std::unit_test::destroy(us);
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
#[test]
|
|
879
|
+
#[expected_failure]
|
|
880
|
+
fun test_buy_seeds_fails_count_zero() {
|
|
881
|
+
let mut ctx = sui::tx_context::dummy();
|
|
882
|
+
let ds = setup_dapp(&mut ctx);
|
|
883
|
+
let mut us = setup_player(100, &mut ctx);
|
|
884
|
+
|
|
885
|
+
shop_system::buy_seeds(&ds, &mut us, CROP_WHEAT, 0, &mut ctx);
|
|
886
|
+
|
|
887
|
+
std::unit_test::destroy(ds);
|
|
888
|
+
std::unit_test::destroy(us);
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
#[test]
|
|
892
|
+
#[expected_failure]
|
|
893
|
+
fun test_buy_seeds_fails_insufficient_gold_by_one() {
|
|
894
|
+
let mut ctx = sui::tx_context::dummy();
|
|
895
|
+
let ds = setup_dapp(&mut ctx);
|
|
896
|
+
let mut us = setup_player(WHEAT_PRICE - 1, &mut ctx); // 4 < 5
|
|
897
|
+
|
|
898
|
+
shop_system::buy_seeds(&ds, &mut us, CROP_WHEAT, 1, &mut ctx);
|
|
899
|
+
|
|
900
|
+
std::unit_test::destroy(ds);
|
|
901
|
+
std::unit_test::destroy(us);
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
// ═════════════════════════════════════════════════════════════════════════════
|
|
905
|
+
// shop_system::buy_extra_plot
|
|
906
|
+
// ═════════════════════════════════════════════════════════════════════════════
|
|
907
|
+
|
|
908
|
+
#[test]
|
|
909
|
+
fun test_buy_extra_plot_increments_plots_and_deducts_gold() {
|
|
910
|
+
let mut ctx = sui::tx_context::dummy();
|
|
911
|
+
let ds = setup_dapp(&mut ctx);
|
|
912
|
+
let mut us = setup_player(300, &mut ctx); // starting: 3 plots, 300 gold
|
|
913
|
+
|
|
914
|
+
shop_system::buy_extra_plot(&ds, &mut us, &mut ctx);
|
|
915
|
+
|
|
916
|
+
assert!(gold::get(&us) == 300 - PLOT_PRICE, 0); // 100
|
|
917
|
+
assert!(profile::get_plots_owned(&us) == 4, 1);
|
|
918
|
+
|
|
919
|
+
std::unit_test::destroy(ds);
|
|
920
|
+
std::unit_test::destroy(us);
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
#[test]
|
|
924
|
+
fun test_buy_extra_plot_exact_gold_boundary() {
|
|
925
|
+
let mut ctx = sui::tx_context::dummy();
|
|
926
|
+
let ds = setup_dapp(&mut ctx);
|
|
927
|
+
let mut us = setup_player(PLOT_PRICE, &mut ctx); // exactly 200
|
|
928
|
+
|
|
929
|
+
shop_system::buy_extra_plot(&ds, &mut us, &mut ctx);
|
|
930
|
+
|
|
931
|
+
assert!(gold::get(&us) == 0, 0);
|
|
932
|
+
assert!(profile::get_plots_owned(&us) == 4, 1);
|
|
933
|
+
|
|
934
|
+
std::unit_test::destroy(ds);
|
|
935
|
+
std::unit_test::destroy(us);
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
#[test]
|
|
939
|
+
fun test_buy_extra_plot_up_to_max_12() {
|
|
940
|
+
let mut ctx = sui::tx_context::dummy();
|
|
941
|
+
let ds = setup_dapp(&mut ctx);
|
|
942
|
+
// Buy 3 extra plots (3 → 6) to verify repeated purchases work
|
|
943
|
+
let mut us = setup_player(2000, &mut ctx);
|
|
944
|
+
|
|
945
|
+
shop_system::buy_extra_plot(&ds, &mut us, &mut ctx);
|
|
946
|
+
shop_system::buy_extra_plot(&ds, &mut us, &mut ctx);
|
|
947
|
+
shop_system::buy_extra_plot(&ds, &mut us, &mut ctx);
|
|
948
|
+
|
|
949
|
+
assert!(profile::get_plots_owned(&us) == 6, 0);
|
|
950
|
+
assert!(gold::get(&us) == 2000 - 3 * PLOT_PRICE, 1); // 2000 - 600 = 1400
|
|
951
|
+
|
|
952
|
+
std::unit_test::destroy(ds);
|
|
953
|
+
std::unit_test::destroy(us);
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
#[test]
|
|
957
|
+
#[expected_failure]
|
|
958
|
+
fun test_buy_extra_plot_fails_not_registered() {
|
|
959
|
+
let mut ctx = sui::tx_context::dummy();
|
|
960
|
+
let ds = setup_dapp(&mut ctx);
|
|
961
|
+
let mut us = init_test::create_user_storage_for_testing(ctx.sender(), &mut ctx);
|
|
962
|
+
|
|
963
|
+
shop_system::buy_extra_plot(&ds, &mut us, &mut ctx);
|
|
964
|
+
|
|
965
|
+
std::unit_test::destroy(ds);
|
|
966
|
+
std::unit_test::destroy(us);
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
#[test]
|
|
970
|
+
#[expected_failure]
|
|
971
|
+
fun test_buy_extra_plot_fails_at_max_12() {
|
|
972
|
+
let mut ctx = sui::tx_context::dummy();
|
|
973
|
+
let ds = setup_dapp(&mut ctx);
|
|
974
|
+
let mut us = init_test::create_user_storage_for_testing(ctx.sender(), &mut ctx);
|
|
975
|
+
gold::set(&mut us, 500, &mut ctx);
|
|
976
|
+
profile::set(&mut us, 0, 12, &mut ctx); // already at max
|
|
977
|
+
|
|
978
|
+
shop_system::buy_extra_plot(&ds, &mut us, &mut ctx);
|
|
979
|
+
|
|
980
|
+
std::unit_test::destroy(ds);
|
|
981
|
+
std::unit_test::destroy(us);
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
#[test]
|
|
985
|
+
#[expected_failure]
|
|
986
|
+
fun test_buy_extra_plot_fails_insufficient_gold_by_one() {
|
|
987
|
+
let mut ctx = sui::tx_context::dummy();
|
|
988
|
+
let ds = setup_dapp(&mut ctx);
|
|
989
|
+
let mut us = setup_player(PLOT_PRICE - 1, &mut ctx); // 199
|
|
990
|
+
|
|
991
|
+
shop_system::buy_extra_plot(&ds, &mut us, &mut ctx);
|
|
992
|
+
|
|
993
|
+
std::unit_test::destroy(ds);
|
|
994
|
+
std::unit_test::destroy(us);
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
// ═════════════════════════════════════════════════════════════════════════════
|
|
998
|
+
// shop_system::sell_crops
|
|
999
|
+
// ═════════════════════════════════════════════════════════════════════════════
|
|
1000
|
+
|
|
1001
|
+
#[test]
|
|
1002
|
+
fun test_sell_wheat_burns_crops_adds_gold() {
|
|
1003
|
+
let mut ctx = sui::tx_context::dummy();
|
|
1004
|
+
let ds = setup_dapp(&mut ctx);
|
|
1005
|
+
let mut us = setup_player(0, &mut ctx);
|
|
1006
|
+
give_crop(&mut us, CROP_WHEAT, 6, &mut ctx);
|
|
1007
|
+
|
|
1008
|
+
shop_system::sell_crops(&ds, &mut us, CROP_WHEAT, 6, &mut ctx);
|
|
1009
|
+
|
|
1010
|
+
assert!(wheat::get(&us) == 0, 0);
|
|
1011
|
+
assert!(gold::get(&us) == 6 * WHEAT_SELL, 1); // 48
|
|
1012
|
+
|
|
1013
|
+
std::unit_test::destroy(ds);
|
|
1014
|
+
std::unit_test::destroy(us);
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
#[test]
|
|
1018
|
+
fun test_sell_corn_correct_price() {
|
|
1019
|
+
let mut ctx = sui::tx_context::dummy();
|
|
1020
|
+
let ds = setup_dapp(&mut ctx);
|
|
1021
|
+
let mut us = setup_player(0, &mut ctx);
|
|
1022
|
+
give_crop(&mut us, CROP_CORN, 4, &mut ctx);
|
|
1023
|
+
|
|
1024
|
+
shop_system::sell_crops(&ds, &mut us, CROP_CORN, 4, &mut ctx);
|
|
1025
|
+
|
|
1026
|
+
assert!(corn::get(&us) == 0, 0);
|
|
1027
|
+
assert!(gold::get(&us) == 4 * CORN_SELL, 1); // 140
|
|
1028
|
+
|
|
1029
|
+
std::unit_test::destroy(ds);
|
|
1030
|
+
std::unit_test::destroy(us);
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
#[test]
|
|
1034
|
+
fun test_sell_partial_amount_leaves_remainder() {
|
|
1035
|
+
let mut ctx = sui::tx_context::dummy();
|
|
1036
|
+
let ds = setup_dapp(&mut ctx);
|
|
1037
|
+
let mut us = setup_player(0, &mut ctx);
|
|
1038
|
+
give_crop(&mut us, CROP_WHEAT, 10, &mut ctx);
|
|
1039
|
+
|
|
1040
|
+
shop_system::sell_crops(&ds, &mut us, CROP_WHEAT, 4, &mut ctx);
|
|
1041
|
+
|
|
1042
|
+
assert!(wheat::get(&us) == 6, 0);
|
|
1043
|
+
assert!(gold::get(&us) == 4 * WHEAT_SELL, 1); // 32
|
|
1044
|
+
|
|
1045
|
+
std::unit_test::destroy(ds);
|
|
1046
|
+
std::unit_test::destroy(us);
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
#[test]
|
|
1050
|
+
fun test_sell_pumpkin_and_carrot_correct_prices() {
|
|
1051
|
+
let mut ctx = sui::tx_context::dummy();
|
|
1052
|
+
let ds = setup_dapp(&mut ctx);
|
|
1053
|
+
let mut us = setup_player(0, &mut ctx);
|
|
1054
|
+
give_crop(&mut us, CROP_PUMPKIN, 2, &mut ctx);
|
|
1055
|
+
give_crop(&mut us, CROP_CARROT, 3, &mut ctx);
|
|
1056
|
+
|
|
1057
|
+
shop_system::sell_crops(&ds, &mut us, CROP_PUMPKIN, 2, &mut ctx);
|
|
1058
|
+
shop_system::sell_crops(&ds, &mut us, CROP_CARROT, 3, &mut ctx);
|
|
1059
|
+
|
|
1060
|
+
assert!(pumpkin::get(&us) == 0, 0);
|
|
1061
|
+
assert!(carrot::get(&us) == 0, 1);
|
|
1062
|
+
assert!(gold::get(&us) == 2 * PUMPKIN_SELL + 3 * CARROT_SELL, 2); // 200 + 360 = 560
|
|
1063
|
+
|
|
1064
|
+
std::unit_test::destroy(ds);
|
|
1065
|
+
std::unit_test::destroy(us);
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
#[test]
|
|
1069
|
+
#[expected_failure]
|
|
1070
|
+
fun test_sell_crops_fails_not_registered() {
|
|
1071
|
+
let mut ctx = sui::tx_context::dummy();
|
|
1072
|
+
let ds = setup_dapp(&mut ctx);
|
|
1073
|
+
let mut us = init_test::create_user_storage_for_testing(ctx.sender(), &mut ctx);
|
|
1074
|
+
|
|
1075
|
+
shop_system::sell_crops(&ds, &mut us, CROP_WHEAT, 1, &mut ctx);
|
|
1076
|
+
|
|
1077
|
+
std::unit_test::destroy(ds);
|
|
1078
|
+
std::unit_test::destroy(us);
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
#[test]
|
|
1082
|
+
#[expected_failure]
|
|
1083
|
+
fun test_sell_crops_fails_invalid_crop_type() {
|
|
1084
|
+
let mut ctx = sui::tx_context::dummy();
|
|
1085
|
+
let ds = setup_dapp(&mut ctx);
|
|
1086
|
+
let mut us = setup_player(0, &mut ctx);
|
|
1087
|
+
|
|
1088
|
+
shop_system::sell_crops(&ds, &mut us, 0, 1, &mut ctx);
|
|
1089
|
+
|
|
1090
|
+
std::unit_test::destroy(ds);
|
|
1091
|
+
std::unit_test::destroy(us);
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
#[test]
|
|
1095
|
+
#[expected_failure]
|
|
1096
|
+
fun test_sell_crops_fails_amount_zero() {
|
|
1097
|
+
let mut ctx = sui::tx_context::dummy();
|
|
1098
|
+
let ds = setup_dapp(&mut ctx);
|
|
1099
|
+
let mut us = setup_player(0, &mut ctx);
|
|
1100
|
+
give_crop(&mut us, CROP_WHEAT, 5, &mut ctx);
|
|
1101
|
+
|
|
1102
|
+
shop_system::sell_crops(&ds, &mut us, CROP_WHEAT, 0, &mut ctx);
|
|
1103
|
+
|
|
1104
|
+
std::unit_test::destroy(ds);
|
|
1105
|
+
std::unit_test::destroy(us);
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
#[test]
|
|
1109
|
+
#[expected_failure]
|
|
1110
|
+
fun test_sell_crops_fails_more_than_owned() {
|
|
1111
|
+
let mut ctx = sui::tx_context::dummy();
|
|
1112
|
+
let ds = setup_dapp(&mut ctx);
|
|
1113
|
+
let mut us = setup_player(0, &mut ctx);
|
|
1114
|
+
give_crop(&mut us, CROP_WHEAT, 3, &mut ctx);
|
|
1115
|
+
|
|
1116
|
+
shop_system::sell_crops(&ds, &mut us, CROP_WHEAT, 4, &mut ctx); // 4 > 3 owned
|
|
1117
|
+
|
|
1118
|
+
std::unit_test::destroy(ds);
|
|
1119
|
+
std::unit_test::destroy(us);
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
// ═════════════════════════════════════════════════════════════════════════════
|
|
1123
|
+
// crow_system::place_scarecrow
|
|
1124
|
+
// ═════════════════════════════════════════════════════════════════════════════
|
|
1125
|
+
|
|
1126
|
+
#[test]
|
|
1127
|
+
fun test_place_scarecrow_deducts_gold_and_sets_expiry() {
|
|
1128
|
+
let mut ctx = sui::tx_context::dummy();
|
|
1129
|
+
let ds = setup_dapp(&mut ctx);
|
|
1130
|
+
let mut us = setup_player(50, &mut ctx);
|
|
1131
|
+
let mut clk = clock::create_for_testing(&mut ctx);
|
|
1132
|
+
clock::set_for_testing(&mut clk, 1000);
|
|
1133
|
+
|
|
1134
|
+
crow_system::place_scarecrow(&ds, &mut us, &clk, &mut ctx);
|
|
1135
|
+
|
|
1136
|
+
assert!(gold::get(&us) == 40, 0); // 50 − 10 = 40
|
|
1137
|
+
assert!(scarecrow::has(&us), 1);
|
|
1138
|
+
// SCARECROW_DURATION = 4 h = 14_400_000 ms
|
|
1139
|
+
assert!(scarecrow::get(&us) == 1000 + 14_400_000, 2);
|
|
1140
|
+
|
|
1141
|
+
clock::destroy_for_testing(clk);
|
|
1142
|
+
std::unit_test::destroy(ds);
|
|
1143
|
+
std::unit_test::destroy(us);
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
#[test]
|
|
1147
|
+
fun test_place_scarecrow_exact_gold_boundary() {
|
|
1148
|
+
let mut ctx = sui::tx_context::dummy();
|
|
1149
|
+
let ds = setup_dapp(&mut ctx);
|
|
1150
|
+
let mut us = setup_player(10, &mut ctx); // exactly 10
|
|
1151
|
+
let clk = clock::create_for_testing(&mut ctx);
|
|
1152
|
+
|
|
1153
|
+
crow_system::place_scarecrow(&ds, &mut us, &clk, &mut ctx);
|
|
1154
|
+
|
|
1155
|
+
assert!(gold::get(&us) == 0, 0);
|
|
1156
|
+
assert!(scarecrow::has(&us), 1);
|
|
1157
|
+
|
|
1158
|
+
clock::destroy_for_testing(clk);
|
|
1159
|
+
std::unit_test::destroy(ds);
|
|
1160
|
+
std::unit_test::destroy(us);
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
#[test]
|
|
1164
|
+
#[expected_failure]
|
|
1165
|
+
fun test_place_scarecrow_fails_not_registered() {
|
|
1166
|
+
let mut ctx = sui::tx_context::dummy();
|
|
1167
|
+
let ds = setup_dapp(&mut ctx);
|
|
1168
|
+
let mut us = init_test::create_user_storage_for_testing(ctx.sender(), &mut ctx);
|
|
1169
|
+
let clk = clock::create_for_testing(&mut ctx);
|
|
1170
|
+
|
|
1171
|
+
crow_system::place_scarecrow(&ds, &mut us, &clk, &mut ctx);
|
|
1172
|
+
|
|
1173
|
+
clock::destroy_for_testing(clk);
|
|
1174
|
+
std::unit_test::destroy(ds);
|
|
1175
|
+
std::unit_test::destroy(us);
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
#[test]
|
|
1179
|
+
#[expected_failure]
|
|
1180
|
+
fun test_place_scarecrow_fails_insufficient_gold_by_one() {
|
|
1181
|
+
let mut ctx = sui::tx_context::dummy();
|
|
1182
|
+
let ds = setup_dapp(&mut ctx);
|
|
1183
|
+
let mut us = setup_player(9, &mut ctx); // 1 short of 10
|
|
1184
|
+
let clk = clock::create_for_testing(&mut ctx);
|
|
1185
|
+
|
|
1186
|
+
crow_system::place_scarecrow(&ds, &mut us, &clk, &mut ctx);
|
|
1187
|
+
|
|
1188
|
+
clock::destroy_for_testing(clk);
|
|
1189
|
+
std::unit_test::destroy(ds);
|
|
1190
|
+
std::unit_test::destroy(us);
|
|
1191
|
+
}
|
|
1192
|
+
}
|