├── .gitignore ├── .tool-versions ├── assets ├── cover.png ├── icon.png ├── marco.everai.jpg └── danielcdz.everai.png ├── overlays └── dev │ ├── move_action.toml │ ├── spawn_action.toml │ └── world_setup.toml ├── .vscode └── settings.json ├── .github ├── templates │ ├── PULL_REQUEST_TEMPLATE.md │ └── ISSUE_TEMPLATE.md ├── workflows │ └── test.yaml ├── mark-dark.svg └── mark-light.svg ├── manifests └── dev │ ├── base │ ├── dojo-base.toml │ ├── dojo-world.toml │ ├── contracts │ │ ├── bytebeasts-actions-648ac931.toml │ │ ├── bytebeasts-bag_system-7ad8a155.toml │ │ ├── bytebeasts-world_setup-674b640b.toml │ │ ├── bytebeasts-move_action-62decdb8.toml │ │ ├── bytebeasts-battle_system-461868ac.toml │ │ ├── bytebeasts-spawn_action-5176c1e8.toml │ │ ├── bytebeasts-leaderboard_system-63f2c524.toml │ │ └── bytebeasts-tournament_system-1f2bbf20.toml │ ├── models │ │ ├── bytebeasts-GameId-344511d3.toml │ │ ├── bytebeasts-Status-6595af0f.toml │ │ ├── bytebeasts-Position-78f28df6.toml │ │ ├── bytebeasts-StatusBattle-161fdb64.toml │ │ ├── bytebeasts-SeasonManager-57ed50e9.toml │ │ ├── bytebeasts-Potion-6a2114b0.toml │ │ ├── bytebeasts-Bag-2571b77d.toml │ │ ├── bytebeasts-AchievementProgress-221f2719.toml │ │ ├── bytebeasts-Mt-37360d30.toml │ │ ├── bytebeasts-Evolution-52744a50.toml │ │ ├── bytebeasts-Leaderboard-7e680376.toml │ │ ├── bytebeasts-Season-52f8bbb6.toml │ │ ├── bytebeasts-Player-14f5e45e.toml │ │ ├── bytebeasts-Battle-55b5860b.toml │ │ ├── bytebeasts-LeaderboardEntry-7237950c.toml │ │ ├── bytebeasts-Game-e91217d7.toml │ │ ├── bytebeasts-Tournament-12bdecb1.toml │ │ ├── bytebeasts-Achievement-58a03b97.toml │ │ ├── bytebeasts-GamePlayer-596ef4a1.toml │ │ ├── bytebeasts-NPC-4c5239ac.toml │ │ └── bytebeasts-Beast-27809d20.toml │ └── abis │ │ ├── dojo-base.json │ │ └── contracts │ │ ├── bytebeasts-world_setup-674b640b.json │ │ ├── bytebeasts-spawn_action-5176c1e8.json │ │ ├── bytebeasts-move_action-62decdb8.json │ │ ├── bytebeasts-bag_system-7ad8a155.json │ │ ├── bytebeasts-actions-648ac931.json │ │ └── bytebeasts-tournament_system-1f2bbf20.json │ └── deployment │ └── abis │ ├── dojo-base.json │ └── contracts │ ├── bytebeasts-world_setup-674b640b.json │ ├── bytebeasts-spawn_action-5176c1e8.json │ ├── bytebeasts-move_action-62decdb8.json │ ├── bytebeasts-bag_system-7ad8a155.json │ └── bytebeasts-actions-648ac931.json ├── scripts ├── setWorld.sh ├── move.sh ├── spawn.sh └── setup.sh ├── src ├── models │ ├── role.cairo │ ├── potion.cairo │ ├── erc20 │ │ ├── models.cairo │ │ └── interface.cairo │ ├── player.cairo │ ├── mt.cairo │ ├── position.cairo │ ├── erc721 │ │ ├── models.cairo │ │ └── interface.cairo │ ├── bag.cairo │ ├── mission_status.cairo │ ├── coordinates.cairo │ ├── achievement_rarity.cairo │ ├── world_elements.cairo │ ├── beast.cairo │ ├── battle.cairo │ ├── tournament.cairo │ ├── game_id.cairo │ ├── game_player.cairo │ ├── achievement_type.cairo │ ├── npc.cairo │ ├── game.cairo │ ├── evolution.cairo │ └── leaderboard.cairo ├── lib.cairo ├── systems │ ├── spawn.cairo │ ├── move.cairo │ ├── bag.cairo │ ├── realms.cairo │ ├── tournament.cairo │ ├── leaderboard.cairo │ └── world_setup.cairo └── tests │ └── test_bag.cairo ├── Scarb.toml ├── dojo_dev.toml ├── LICENSE ├── Makefile ├── Scarb.lock ├── docs └── contribution │ └── CONTRIBUTION.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | -------------------------------------------------------------------------------- /.tool-versions: -------------------------------------------------------------------------------- 1 | dojo 1.0.0-alpha.5 2 | scarb 2.7.0 3 | -------------------------------------------------------------------------------- /assets/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ByteBeasts/ByteBeastsBackend/HEAD/assets/cover.png -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ByteBeasts/ByteBeastsBackend/HEAD/assets/icon.png -------------------------------------------------------------------------------- /overlays/dev/move_action.toml: -------------------------------------------------------------------------------- 1 | tag = "bytebeasts-move_action" 2 | writes = ["bytebeasts-Position"] 3 | -------------------------------------------------------------------------------- /assets/marco.everai.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ByteBeasts/ByteBeastsBackend/HEAD/assets/marco.everai.jpg -------------------------------------------------------------------------------- /assets/danielcdz.everai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ByteBeasts/ByteBeastsBackend/HEAD/assets/danielcdz.everai.png -------------------------------------------------------------------------------- /overlays/dev/spawn_action.toml: -------------------------------------------------------------------------------- 1 | tag = "bytebeasts-spawn_action" 2 | writes = [ "bytebeasts-Beast", "bytebeasts-Mt", "bytebeasts-Player", "bytebeasts-Potion","bytebeasts-Position"] 3 | -------------------------------------------------------------------------------- /overlays/dev/world_setup.toml: -------------------------------------------------------------------------------- 1 | tag = "bytebeasts-world_setup" 2 | writes = ["bytebeasts-Beast", "bytebeasts-Mt", "bytebeasts-Player", "bytebeasts-Potion","bytebeasts-Position"] 3 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cairo1.enableLanguageServer": true, 3 | "cairo1.enableScarb": true, 4 | "cairo1.languageServerPath": "${userHome}/.dojo/bin/dojo-language-server" 5 | } 6 | -------------------------------------------------------------------------------- /.github/templates/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Pull Request Overview 2 | ### 📝 Summary 3 | - Closes #(issue) 4 | - 5 | ### 🔄 Changes Made 6 | - 7 | ### 🔧 Tests Results 8 | - 9 | 10 | ### 🔜 Next Steps 11 | - 12 | 13 | -------------------------------------------------------------------------------- /manifests/dev/base/dojo-base.toml: -------------------------------------------------------------------------------- 1 | kind = "Class" 2 | class_hash = "0x2427dd10a58850ac9a5ca6ce04b7771b05330fd18f2e481831ad903b969e6b2" 3 | original_class_hash = "0x2427dd10a58850ac9a5ca6ce04b7771b05330fd18f2e481831ad903b969e6b2" 4 | abi = "manifests/dev/base/abis/dojo-base.json" 5 | tag = "dojo-base" 6 | manifest_name = "dojo-base" 7 | -------------------------------------------------------------------------------- /manifests/dev/base/dojo-world.toml: -------------------------------------------------------------------------------- 1 | kind = "Class" 2 | class_hash = "0x76ced5a15cb43c7be7176cff4779cd57c56638a46ddf2c9da709d22298c5e5a" 3 | original_class_hash = "0x76ced5a15cb43c7be7176cff4779cd57c56638a46ddf2c9da709d22298c5e5a" 4 | abi = "manifests/dev/base/abis/dojo-world.json" 5 | tag = "dojo-world" 6 | manifest_name = "dojo-world" 7 | -------------------------------------------------------------------------------- /.github/templates/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Issue 2 | ### 📖 Description 3 | - Issue description 4 | ### 📓 Summary 5 | - Brief summary of the issue 6 | ### 📦 Deliverable 7 | - File or files to deliverable in this issue 8 | ### 📚 References 9 | - Some references to the repository 10 | ### ⚠️ Notes 11 | - Important notes for the issue 12 | -------------------------------------------------------------------------------- /scripts/setWorld.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | pushd $(dirname "$0")/.. 4 | 5 | export RPC_URL="http://0.0.0.0:5050"; 6 | 7 | export WORLD_ADDRESS=$(cat ./manifests/dev/deployment/manifest.json | jq -r '.world.address') 8 | 9 | echo $WORLD_ADDRESS 10 | 11 | # sozo execute --world 12 | sozo execute --world $WORLD_ADDRESS world_setup setWorld --wait 13 | -------------------------------------------------------------------------------- /scripts/move.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | pushd $(dirname "$0")/.. 4 | 5 | export RPC_URL="http://0.0.0.0:5050"; 6 | 7 | export WORLD_ADDRESS="$(cat ./manifests/dev/deployment/manifest.json | jq -r '.world.address')" 8 | 9 | echo $WORLD_ADDRESS 10 | 11 | # sozo execute --world 12 | sozo execute --world $WORLD_ADDRESS move_action move -c 1,15,15 --wait 13 | -------------------------------------------------------------------------------- /scripts/spawn.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | pushd $(dirname "$0")/.. 4 | 5 | export RPC_URL="http://0.0.0.0:5050"; 6 | 7 | export WORLD_ADDRESS="$(cat ./manifests/dev/deployment/manifest.json | jq -r '.world.address')" 8 | 9 | echo $WORLD_ADDRESS 10 | 11 | # sozo execute --world 12 | sozo execute --world $WORLD_ADDRESS spawn_action spawn -c 1 --wait 13 | -------------------------------------------------------------------------------- /src/models/role.cairo: -------------------------------------------------------------------------------- 1 | #[derive(Serde, Copy, Drop, Introspect)] 2 | pub enum Role { 3 | Vendor, 4 | Trainer, 5 | Guide, 6 | QuestGiver, 7 | } 8 | 9 | impl RoleIntoFelt252 of Into { 10 | fn into(self: Role) -> felt252 { 11 | match self { 12 | Role::Vendor => 0, 13 | Role::Trainer => 1, 14 | Role::Guide => 2, 15 | Role::QuestGiver => 3, 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /scripts/setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | if [ -d "target" ]; then 5 | rm -rf "target" 6 | fi 7 | 8 | if [ -d "manifests" ]; then 9 | rm -rf "manifests" 10 | fi 11 | 12 | echo "sozo build && sozo migrate apply" 13 | sozo build && sozo migrate apply 14 | 15 | echo -e "\n✅ Setup finish!" 16 | 17 | export world_address=$(cat ./manifests/dev/deployment/manifest.json | jq -r '.world.address') 18 | 19 | echo -e "\n✅ Init Torii!" 20 | torii --world $world_address --allowed-origins "*" 21 | -------------------------------------------------------------------------------- /manifests/dev/base/contracts/bytebeasts-actions-648ac931.toml: -------------------------------------------------------------------------------- 1 | kind = "DojoContract" 2 | class_hash = "0x7a662a2c7e8067fd633c3840f51c671a18c2e71901995fe791281c07c855aa0" 3 | original_class_hash = "0x7a662a2c7e8067fd633c3840f51c671a18c2e71901995fe791281c07c855aa0" 4 | base_class_hash = "0x0" 5 | abi = "manifests/dev/base/abis/contracts/bytebeasts-actions-648ac931.json" 6 | reads = [] 7 | writes = [] 8 | init_calldata = [] 9 | tag = "bytebeasts-actions" 10 | manifest_name = "bytebeasts-actions-648ac931" 11 | -------------------------------------------------------------------------------- /manifests/dev/base/contracts/bytebeasts-bag_system-7ad8a155.toml: -------------------------------------------------------------------------------- 1 | kind = "DojoContract" 2 | class_hash = "0x51aaf7a580665ebd6d7d32e2340f0e8b6850296fc1ad389c74a293d1a26029f" 3 | original_class_hash = "0x51aaf7a580665ebd6d7d32e2340f0e8b6850296fc1ad389c74a293d1a26029f" 4 | base_class_hash = "0x0" 5 | abi = "manifests/dev/base/abis/contracts/bytebeasts-bag_system-7ad8a155.json" 6 | reads = [] 7 | writes = [] 8 | init_calldata = [] 9 | tag = "bytebeasts-bag_system" 10 | manifest_name = "bytebeasts-bag_system-7ad8a155" 11 | -------------------------------------------------------------------------------- /manifests/dev/base/contracts/bytebeasts-world_setup-674b640b.toml: -------------------------------------------------------------------------------- 1 | kind = "DojoContract" 2 | class_hash = "0xad9d2da0783e3a31f6198d7c355bd293e496019e0e335449377a2c0146880" 3 | original_class_hash = "0xad9d2da0783e3a31f6198d7c355bd293e496019e0e335449377a2c0146880" 4 | base_class_hash = "0x0" 5 | abi = "manifests/dev/base/abis/contracts/bytebeasts-world_setup-674b640b.json" 6 | reads = [] 7 | writes = [] 8 | init_calldata = [] 9 | tag = "bytebeasts-world_setup" 10 | manifest_name = "bytebeasts-world_setup-674b640b" 11 | -------------------------------------------------------------------------------- /manifests/dev/base/contracts/bytebeasts-move_action-62decdb8.toml: -------------------------------------------------------------------------------- 1 | kind = "DojoContract" 2 | class_hash = "0x6ab57932e6f1d360557867a6775d89180d623a481695d4349f6d356c8cd31ee" 3 | original_class_hash = "0x6ab57932e6f1d360557867a6775d89180d623a481695d4349f6d356c8cd31ee" 4 | base_class_hash = "0x0" 5 | abi = "manifests/dev/base/abis/contracts/bytebeasts-move_action-62decdb8.json" 6 | reads = [] 7 | writes = [] 8 | init_calldata = [] 9 | tag = "bytebeasts-move_action" 10 | manifest_name = "bytebeasts-move_action-62decdb8" 11 | -------------------------------------------------------------------------------- /manifests/dev/base/contracts/bytebeasts-battle_system-461868ac.toml: -------------------------------------------------------------------------------- 1 | kind = "DojoContract" 2 | class_hash = "0x22eff2287b74c9f79832f32132c8154f28f916551d8650c8425f6c1c49adc31" 3 | original_class_hash = "0x22eff2287b74c9f79832f32132c8154f28f916551d8650c8425f6c1c49adc31" 4 | base_class_hash = "0x0" 5 | abi = "manifests/dev/base/abis/contracts/bytebeasts-battle_system-461868ac.json" 6 | reads = [] 7 | writes = [] 8 | init_calldata = [] 9 | tag = "bytebeasts-battle_system" 10 | manifest_name = "bytebeasts-battle_system-461868ac" 11 | -------------------------------------------------------------------------------- /manifests/dev/base/contracts/bytebeasts-spawn_action-5176c1e8.toml: -------------------------------------------------------------------------------- 1 | kind = "DojoContract" 2 | class_hash = "0x394b6a9219ec1e5e1e3afdec390794e017870eb56b58ad18252d3c1eaf2a0f0" 3 | original_class_hash = "0x394b6a9219ec1e5e1e3afdec390794e017870eb56b58ad18252d3c1eaf2a0f0" 4 | base_class_hash = "0x0" 5 | abi = "manifests/dev/base/abis/contracts/bytebeasts-spawn_action-5176c1e8.json" 6 | reads = [] 7 | writes = [] 8 | init_calldata = [] 9 | tag = "bytebeasts-spawn_action" 10 | manifest_name = "bytebeasts-spawn_action-5176c1e8" 11 | -------------------------------------------------------------------------------- /manifests/dev/base/contracts/bytebeasts-leaderboard_system-63f2c524.toml: -------------------------------------------------------------------------------- 1 | kind = "DojoContract" 2 | class_hash = "0x1a7893ed15f19f9e8233d342a0a0bea37c58fdcb54b10d867fb2269c77de125" 3 | original_class_hash = "0x1a7893ed15f19f9e8233d342a0a0bea37c58fdcb54b10d867fb2269c77de125" 4 | base_class_hash = "0x0" 5 | abi = "manifests/dev/base/abis/contracts/bytebeasts-leaderboard_system-63f2c524.json" 6 | reads = [] 7 | writes = [] 8 | init_calldata = [] 9 | tag = "bytebeasts-leaderboard_system" 10 | manifest_name = "bytebeasts-leaderboard_system-63f2c524" 11 | -------------------------------------------------------------------------------- /manifests/dev/base/contracts/bytebeasts-tournament_system-1f2bbf20.toml: -------------------------------------------------------------------------------- 1 | kind = "DojoContract" 2 | class_hash = "0x20aead2ca71d2f0bfcbfa28a41b4b7687aa1af2579394c256ca0c4dc73bd2e8" 3 | original_class_hash = "0x20aead2ca71d2f0bfcbfa28a41b4b7687aa1af2579394c256ca0c4dc73bd2e8" 4 | base_class_hash = "0x0" 5 | abi = "manifests/dev/base/abis/contracts/bytebeasts-tournament_system-1f2bbf20.json" 6 | reads = [] 7 | writes = [] 8 | init_calldata = [] 9 | tag = "bytebeasts-tournament_system" 10 | manifest_name = "bytebeasts-tournament_system-1f2bbf20" 11 | -------------------------------------------------------------------------------- /manifests/dev/base/models/bytebeasts-GameId-344511d3.toml: -------------------------------------------------------------------------------- 1 | kind = "DojoModel" 2 | class_hash = "0x7dc1689aa3f1e6b123cadfed4066a70f09be69c9a166bfe824c61b916925efe" 3 | original_class_hash = "0x7dc1689aa3f1e6b123cadfed4066a70f09be69c9a166bfe824c61b916925efe" 4 | abi = "manifests/dev/base/abis/models/bytebeasts-GameId-344511d3.json" 5 | tag = "bytebeasts-GameId" 6 | manifest_name = "bytebeasts-GameId-344511d3" 7 | 8 | [[members]] 9 | name = "id" 10 | type = "u32" 11 | key = true 12 | 13 | [[members]] 14 | name = "game_id" 15 | type = "u128" 16 | key = false 17 | -------------------------------------------------------------------------------- /manifests/dev/base/models/bytebeasts-Status-6595af0f.toml: -------------------------------------------------------------------------------- 1 | kind = "DojoModel" 2 | class_hash = "0xe446a8c3773fbfae6e2e0e87a6d1db12143224cf47e217e12bf9cfc76428ef" 3 | original_class_hash = "0xe446a8c3773fbfae6e2e0e87a6d1db12143224cf47e217e12bf9cfc76428ef" 4 | abi = "manifests/dev/base/abis/models/bytebeasts-Status-6595af0f.json" 5 | tag = "bytebeasts-Status" 6 | manifest_name = "bytebeasts-Status-6595af0f" 7 | 8 | [[members]] 9 | name = "player_id" 10 | type = "u32" 11 | key = true 12 | 13 | [[members]] 14 | name = "message" 15 | type = "felt252" 16 | key = false 17 | -------------------------------------------------------------------------------- /manifests/dev/base/models/bytebeasts-Position-78f28df6.toml: -------------------------------------------------------------------------------- 1 | kind = "DojoModel" 2 | class_hash = "0x91da9f380b960e2dc7f9a59d4e1242ed718590d2270fd28e2311a5e1ee54f2" 3 | original_class_hash = "0x91da9f380b960e2dc7f9a59d4e1242ed718590d2270fd28e2311a5e1ee54f2" 4 | abi = "manifests/dev/base/abis/models/bytebeasts-Position-78f28df6.json" 5 | tag = "bytebeasts-Position" 6 | manifest_name = "bytebeasts-Position-78f28df6" 7 | 8 | [[members]] 9 | name = "player" 10 | type = "Player" 11 | key = true 12 | 13 | [[members]] 14 | name = "coordinates" 15 | type = "Coordinates" 16 | key = false 17 | -------------------------------------------------------------------------------- /manifests/dev/base/models/bytebeasts-StatusBattle-161fdb64.toml: -------------------------------------------------------------------------------- 1 | kind = "DojoModel" 2 | class_hash = "0x5ba495f80b653be6df964eb97ac2e7b3f7f72508d17b54b1d51595231db8fae" 3 | original_class_hash = "0x5ba495f80b653be6df964eb97ac2e7b3f7f72508d17b54b1d51595231db8fae" 4 | abi = "manifests/dev/base/abis/models/bytebeasts-StatusBattle-161fdb64.json" 5 | tag = "bytebeasts-StatusBattle" 6 | manifest_name = "bytebeasts-StatusBattle-161fdb64" 7 | 8 | [[members]] 9 | name = "battle_id" 10 | type = "u32" 11 | key = true 12 | 13 | [[members]] 14 | name = "message" 15 | type = "felt252" 16 | key = false 17 | -------------------------------------------------------------------------------- /manifests/dev/base/models/bytebeasts-SeasonManager-57ed50e9.toml: -------------------------------------------------------------------------------- 1 | kind = "DojoModel" 2 | class_hash = "0x6795f48396469dd05f2357a86bf37d0392c24d938bc0972006834ac365b62c" 3 | original_class_hash = "0x6795f48396469dd05f2357a86bf37d0392c24d938bc0972006834ac365b62c" 4 | abi = "manifests/dev/base/abis/models/bytebeasts-SeasonManager-57ed50e9.json" 5 | tag = "bytebeasts-SeasonManager" 6 | manifest_name = "bytebeasts-SeasonManager-57ed50e9" 7 | 8 | [[members]] 9 | name = "manager_id" 10 | type = "u64" 11 | key = true 12 | 13 | [[members]] 14 | name = "seasons" 15 | type = "Array" 16 | key = false 17 | -------------------------------------------------------------------------------- /Scarb.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | cairo-version = "=2.7.0" 3 | name = "bytebeasts" 4 | version = "0.1.0" 5 | 6 | [cairo] 7 | sierra-replace-ids = true 8 | 9 | [scripts] 10 | migrate = "sozo build && sozo migrate apply" 11 | spawn = "./scripts/spawn.sh" 12 | move = "./scripts/move.sh" 13 | 14 | [dependencies] 15 | dojo = { git = "https://github.com/dojoengine/dojo", tag = "v1.0.0-alpha.5" } 16 | # Alexandria versions with tag greater that "cairo-v2.5.4" conflict with dojo engine 17 | alexandria_sorting = { git = "https://github.com/keep-starknet-strange/alexandria.git", tag = "cairo-v2.6.0" } 18 | 19 | [[target.dojo]] 20 | -------------------------------------------------------------------------------- /manifests/dev/base/models/bytebeasts-Potion-6a2114b0.toml: -------------------------------------------------------------------------------- 1 | kind = "DojoModel" 2 | class_hash = "0x4eac23f35a0e71954b8f000d9d8999579ba49ffc918e8b78924562449bdf8d4" 3 | original_class_hash = "0x4eac23f35a0e71954b8f000d9d8999579ba49ffc918e8b78924562449bdf8d4" 4 | abi = "manifests/dev/base/abis/models/bytebeasts-Potion-6a2114b0.json" 5 | tag = "bytebeasts-Potion" 6 | manifest_name = "bytebeasts-Potion-6a2114b0" 7 | 8 | [[members]] 9 | name = "potion_id" 10 | type = "u32" 11 | key = true 12 | 13 | [[members]] 14 | name = "potion_name" 15 | type = "felt252" 16 | key = false 17 | 18 | [[members]] 19 | name = "potion_effect" 20 | type = "u32" 21 | key = false 22 | -------------------------------------------------------------------------------- /.github/workflows/test.yaml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | pull_request: 6 | 7 | jobs: 8 | sozo-test: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v3 12 | - run: curl -L https://install.dojoengine.org | bash 13 | - run: /home/runner/.config/.dojo/bin/dojoup -v v1.0.0-alpha.5 14 | - run: | 15 | /home/runner/.config/.dojo/bin/sozo build 16 | /home/runner/.config/.dojo/bin/sozo test 17 | if [[ `git status --porcelain` ]]; then 18 | echo The git repo is dirty 19 | echo "Make sure to run \"sozo build\" after changing Scarb.toml" 20 | exit 1 21 | fi 22 | -------------------------------------------------------------------------------- /manifests/dev/base/models/bytebeasts-Bag-2571b77d.toml: -------------------------------------------------------------------------------- 1 | kind = "DojoModel" 2 | class_hash = "0x4e0fab7bc052de0008be5606ad3b37576afd2bda323443fc98a8f37bcc10c1c" 3 | original_class_hash = "0x4e0fab7bc052de0008be5606ad3b37576afd2bda323443fc98a8f37bcc10c1c" 4 | abi = "manifests/dev/base/abis/models/bytebeasts-Bag-2571b77d.json" 5 | tag = "bytebeasts-Bag" 6 | manifest_name = "bytebeasts-Bag-2571b77d" 7 | 8 | [[members]] 9 | name = "bag_id" 10 | type = "u32" 11 | key = true 12 | 13 | [[members]] 14 | name = "player_id" 15 | type = "u32" 16 | key = true 17 | 18 | [[members]] 19 | name = "max_capacity" 20 | type = "u32" 21 | key = false 22 | 23 | [[members]] 24 | name = "potions" 25 | type = "Array" 26 | key = false 27 | -------------------------------------------------------------------------------- /src/models/potion.cairo: -------------------------------------------------------------------------------- 1 | #[derive(Copy, Drop, Serde)] 2 | #[dojo::model] 3 | struct Potion { 4 | #[key] 5 | pub potion_id: u32, 6 | pub potion_name: felt252, 7 | pub potion_effect: u32, 8 | } 9 | 10 | #[cfg(test)] 11 | mod tests { 12 | use bytebeasts::{models::{potion::Potion},}; 13 | 14 | #[test] 15 | fn test_potion_initialization() { 16 | let potion = Potion { 17 | potion_id: 1, 18 | potion_name: 0, // Assume potion_name is felt252 type 19 | potion_effect: 50, // Heals 50 HP 20 | }; 21 | 22 | assert_eq!(potion.potion_id, 1, "Potion ID should be 1"); 23 | assert_eq!(potion.potion_effect, 50, "Potion effect should be 50"); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /dojo_dev.toml: -------------------------------------------------------------------------------- 1 | [world] 2 | name = "Bytebeasts" 3 | description = "The official Byte Beasts guide, the quickest and most streamlined way to get your Dojo Autonomous World up and running. This guide will assist you with the initial setup, from cloning the repository to deploying your world." 4 | seed = "bytebeasts" 5 | 6 | [namespace] 7 | default = "bytebeasts" 8 | 9 | [env] 10 | rpc_url = "http://0.0.0.0:5050" 11 | # Default account for katana with seed = 0 12 | account_address = "0xb3ff441a68610b30fd5e2abbf3a1548eb6ba6f3559f2862bf2dc757e5828ca" 13 | private_key = "0x2bbf4f9fd0bbb2e60b0316c1fe0b76cf7a4d0198bd493ced9b8df2a3a24d68a" 14 | # world_address = "0x3fc79ccfd72c1450d2ccb73c5c521a7ec68b6c6af0caf96a0f1c39ce58876c8" # Uncomment and update this line with your world address. 15 | -------------------------------------------------------------------------------- /src/models/erc20/models.cairo: -------------------------------------------------------------------------------- 1 | // Starknet imports 2 | 3 | use starknet::ContractAddress; 4 | 5 | #[dojo::model] 6 | #[derive(Copy, Drop, Serde)] 7 | struct ERC20Balance { 8 | #[key] 9 | token: ContractAddress, 10 | #[key] 11 | account: ContractAddress, 12 | amount: u256, 13 | } 14 | 15 | #[dojo::model] 16 | #[derive(Copy, Drop, Serde)] 17 | struct ERC20Allowance { 18 | #[key] 19 | token: ContractAddress, 20 | #[key] 21 | owner: ContractAddress, 22 | #[key] 23 | spender: ContractAddress, 24 | amount: u256, 25 | } 26 | 27 | #[dojo::model] 28 | #[derive(Copy, Drop, Serde)] 29 | struct ERC20Meta { 30 | #[key] 31 | token: ContractAddress, 32 | name: felt252, 33 | symbol: felt252, 34 | total_supply: u256, 35 | } 36 | -------------------------------------------------------------------------------- /manifests/dev/base/models/bytebeasts-AchievementProgress-221f2719.toml: -------------------------------------------------------------------------------- 1 | kind = "DojoModel" 2 | class_hash = "0x494e5a6534846cd68b493aab6f9954333c64c854dbe99144c427f4301477f15" 3 | original_class_hash = "0x494e5a6534846cd68b493aab6f9954333c64c854dbe99144c427f4301477f15" 4 | abi = "manifests/dev/base/abis/models/bytebeasts-AchievementProgress-221f2719.json" 5 | tag = "bytebeasts-AchievementProgress" 6 | manifest_name = "bytebeasts-AchievementProgress-221f2719" 7 | 8 | [[members]] 9 | name = "player_id" 10 | type = "u64" 11 | key = true 12 | 13 | [[members]] 14 | name = "achievement_id" 15 | type = "u64" 16 | key = false 17 | 18 | [[members]] 19 | name = "progress" 20 | type = "u32" 21 | key = false 22 | 23 | [[members]] 24 | name = "is_unlocked" 25 | type = "bool" 26 | key = false 27 | -------------------------------------------------------------------------------- /manifests/dev/base/models/bytebeasts-Mt-37360d30.toml: -------------------------------------------------------------------------------- 1 | kind = "DojoModel" 2 | class_hash = "0x341a07493baed313e741253a241aa31fc9d40a9c373cd2bae49f85ab66f98cc" 3 | original_class_hash = "0x341a07493baed313e741253a241aa31fc9d40a9c373cd2bae49f85ab66f98cc" 4 | abi = "manifests/dev/base/abis/models/bytebeasts-Mt-37360d30.json" 5 | tag = "bytebeasts-Mt" 6 | manifest_name = "bytebeasts-Mt-37360d30" 7 | 8 | [[members]] 9 | name = "mt_id" 10 | type = "u32" 11 | key = true 12 | 13 | [[members]] 14 | name = "mt_name" 15 | type = "felt252" 16 | key = false 17 | 18 | [[members]] 19 | name = "mt_type" 20 | type = "WorldElements" 21 | key = false 22 | 23 | [[members]] 24 | name = "mt_power" 25 | type = "u32" 26 | key = false 27 | 28 | [[members]] 29 | name = "mt_accuracy" 30 | type = "u32" 31 | key = false 32 | -------------------------------------------------------------------------------- /manifests/dev/base/models/bytebeasts-Evolution-52744a50.toml: -------------------------------------------------------------------------------- 1 | kind = "DojoModel" 2 | class_hash = "0x2d40a7cd64e9c72b855b55fddaa9de2d4c80aadce9f8a4276bf3d859cb18a9c" 3 | original_class_hash = "0x2d40a7cd64e9c72b855b55fddaa9de2d4c80aadce9f8a4276bf3d859cb18a9c" 4 | abi = "manifests/dev/base/abis/models/bytebeasts-Evolution-52744a50.json" 5 | tag = "bytebeasts-Evolution" 6 | manifest_name = "bytebeasts-Evolution-52744a50" 7 | 8 | [[members]] 9 | name = "base_beast_id" 10 | type = "u32" 11 | key = true 12 | 13 | [[members]] 14 | name = "evolved_beast_id" 15 | type = "u32" 16 | key = false 17 | 18 | [[members]] 19 | name = "level_requirement" 20 | type = "u32" 21 | key = false 22 | 23 | [[members]] 24 | name = "required_battles" 25 | type = "u32" 26 | key = false 27 | 28 | [[members]] 29 | name = "required_item" 30 | type = "Option" 31 | key = false 32 | -------------------------------------------------------------------------------- /manifests/dev/base/models/bytebeasts-Leaderboard-7e680376.toml: -------------------------------------------------------------------------------- 1 | kind = "DojoModel" 2 | class_hash = "0x13d964c4091be478133a4aadbb278da14229f77225ce8da5dd246e42abc7ac0" 3 | original_class_hash = "0x13d964c4091be478133a4aadbb278da14229f77225ce8da5dd246e42abc7ac0" 4 | abi = "manifests/dev/base/abis/models/bytebeasts-Leaderboard-7e680376.json" 5 | tag = "bytebeasts-Leaderboard" 6 | manifest_name = "bytebeasts-Leaderboard-7e680376" 7 | 8 | [[members]] 9 | name = "leaderboard_id" 10 | type = "u64" 11 | key = true 12 | 13 | [[members]] 14 | name = "name" 15 | type = "felt252" 16 | key = false 17 | 18 | [[members]] 19 | name = "description" 20 | type = "felt252" 21 | key = false 22 | 23 | [[members]] 24 | name = "entries" 25 | type = "Array" 26 | key = false 27 | 28 | [[members]] 29 | name = "last_updated" 30 | type = "u64" 31 | key = false 32 | -------------------------------------------------------------------------------- /src/lib.cairo: -------------------------------------------------------------------------------- 1 | mod systems { 2 | mod battle; 3 | mod realms; 4 | mod move; 5 | mod spawn; 6 | mod world_setup; 7 | mod bag; 8 | mod tournament; 9 | mod leaderboard; 10 | } 11 | 12 | mod models { 13 | mod bag; 14 | mod battle; 15 | mod beast; 16 | mod coordinates; 17 | mod game_id; 18 | mod game_player; 19 | mod game; 20 | mod mission_status; 21 | mod mt; 22 | mod npc; 23 | mod player; 24 | mod position; 25 | mod potion; 26 | mod role; 27 | mod world_elements; 28 | mod achievement_rarity; 29 | mod achievement_type; 30 | mod achievements; 31 | mod tournament; 32 | mod season; 33 | mod leaderboard; 34 | mod evolution; 35 | } 36 | 37 | mod tests { 38 | mod test_battle; 39 | mod test_bag; 40 | mod test_tournament; 41 | mod test_leaderboard; 42 | } 43 | -------------------------------------------------------------------------------- /manifests/dev/base/models/bytebeasts-Season-52f8bbb6.toml: -------------------------------------------------------------------------------- 1 | kind = "DojoModel" 2 | class_hash = "0x7a8bee9882da24371365f5e6531ed532e9deb91c5b5173d7d230dec53c5c337" 3 | original_class_hash = "0x7a8bee9882da24371365f5e6531ed532e9deb91c5b5173d7d230dec53c5c337" 4 | abi = "manifests/dev/base/abis/models/bytebeasts-Season-52f8bbb6.json" 5 | tag = "bytebeasts-Season" 6 | manifest_name = "bytebeasts-Season-52f8bbb6" 7 | 8 | [[members]] 9 | name = "season_id" 10 | type = "u64" 11 | key = true 12 | 13 | [[members]] 14 | name = "name" 15 | type = "felt252" 16 | key = false 17 | 18 | [[members]] 19 | name = "start_date" 20 | type = "u64" 21 | key = false 22 | 23 | [[members]] 24 | name = "end_date" 25 | type = "u64" 26 | key = false 27 | 28 | [[members]] 29 | name = "is_active" 30 | type = "bool" 31 | key = false 32 | 33 | [[members]] 34 | name = "active_players" 35 | type = "Array" 36 | key = false 37 | -------------------------------------------------------------------------------- /src/models/player.cairo: -------------------------------------------------------------------------------- 1 | #[derive(Copy, Drop, Serde)] 2 | #[dojo::model] 3 | struct Player { 4 | #[key] 5 | pub player_id: u32, 6 | pub player_name: felt252, 7 | pub beast_1: u32, 8 | pub beast_2: u32, 9 | pub beast_3: u32, 10 | pub beast_4: u32, 11 | pub potions: u32, 12 | } 13 | 14 | #[cfg(test)] 15 | mod tests { 16 | use bytebeasts::{models::{player::Player},}; 17 | 18 | #[test] 19 | fn test_player_initialization() { 20 | let player = Player { 21 | player_id: 1, 22 | player_name: 'Hero', 23 | beast_1: 1, 24 | beast_2: 2, 25 | beast_3: 3, 26 | beast_4: 4, 27 | potions: 5, 28 | }; 29 | 30 | assert_eq!(player.player_name, 'Hero', "Player name should be 'Hero'"); 31 | assert_eq!(player.potions, 5, "Player should have 5 potions"); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/models/mt.cairo: -------------------------------------------------------------------------------- 1 | use super::world_elements::WorldElements; 2 | 3 | #[derive(Copy, Drop, Serde)] 4 | #[dojo::model] 5 | pub struct Mt { 6 | #[key] 7 | pub mt_id: u32, 8 | pub mt_name: felt252, 9 | pub mt_type: WorldElements, 10 | pub mt_power: u32, 11 | pub mt_accuracy: u32, 12 | } 13 | 14 | #[cfg(test)] 15 | mod tests { 16 | use bytebeasts::{models::{mt::Mt, world_elements::WorldElements},}; 17 | 18 | #[test] 19 | fn test_mt_initialization() { 20 | let mt = Mt { 21 | mt_id: 1, 22 | mt_name: 0, // Assume mt_name is felt252 type 23 | mt_type: WorldElements::Light, 24 | mt_power: 75, 25 | mt_accuracy: 90, 26 | }; 27 | 28 | assert_eq!(mt.mt_id, 1, "MT ID should be 1"); 29 | assert_eq!(mt.mt_power, 75, "MT power should be 75"); 30 | assert_eq!(mt.mt_accuracy, 90, "MT accuracy should be 90"); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/systems/spawn.cairo: -------------------------------------------------------------------------------- 1 | use bytebeasts::{ 2 | models::{player::Player, coordinates::Coordinates, position::Position}, 3 | }; 4 | 5 | #[dojo::interface] 6 | trait ISpawnAction { 7 | fn spawn(ref world: IWorldDispatcher, player_id: u32); 8 | } 9 | 10 | #[dojo::contract] 11 | mod spawn_action { 12 | use super::ISpawnAction; 13 | use starknet::{ContractAddress, get_caller_address}; 14 | use bytebeasts::{ 15 | models::{player::Player, coordinates::Coordinates, position::Position}, 16 | }; 17 | 18 | #[abi(embed_v0)] 19 | impl SpawnActionImpl of ISpawnAction { 20 | fn spawn(ref world: IWorldDispatcher, player_id: u32) { 21 | let player_from_world = get!(world, player_id, (Player)); 22 | 23 | set!( 24 | world, 25 | (Position { player: player_from_world, coordinates: Coordinates { x: 10, y: 10 } },) 26 | ); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /manifests/dev/base/models/bytebeasts-Player-14f5e45e.toml: -------------------------------------------------------------------------------- 1 | kind = "DojoModel" 2 | class_hash = "0x5d992305e6f7ce0965d5bbe71e33cab817c31514ba83c8fca4610ab574e8016" 3 | original_class_hash = "0x5d992305e6f7ce0965d5bbe71e33cab817c31514ba83c8fca4610ab574e8016" 4 | abi = "manifests/dev/base/abis/models/bytebeasts-Player-14f5e45e.json" 5 | tag = "bytebeasts-Player" 6 | manifest_name = "bytebeasts-Player-14f5e45e" 7 | 8 | [[members]] 9 | name = "player_id" 10 | type = "u32" 11 | key = true 12 | 13 | [[members]] 14 | name = "player_name" 15 | type = "felt252" 16 | key = false 17 | 18 | [[members]] 19 | name = "beast_1" 20 | type = "u32" 21 | key = false 22 | 23 | [[members]] 24 | name = "beast_2" 25 | type = "u32" 26 | key = false 27 | 28 | [[members]] 29 | name = "beast_3" 30 | type = "u32" 31 | key = false 32 | 33 | [[members]] 34 | name = "beast_4" 35 | type = "u32" 36 | key = false 37 | 38 | [[members]] 39 | name = "potions" 40 | type = "u32" 41 | key = false 42 | -------------------------------------------------------------------------------- /manifests/dev/base/models/bytebeasts-Battle-55b5860b.toml: -------------------------------------------------------------------------------- 1 | kind = "DojoModel" 2 | class_hash = "0x239c54e950b5c50d445f9a8db758ea0af1440b75a5f1921dfe014b927476c32" 3 | original_class_hash = "0x239c54e950b5c50d445f9a8db758ea0af1440b75a5f1921dfe014b927476c32" 4 | abi = "manifests/dev/base/abis/models/bytebeasts-Battle-55b5860b.json" 5 | tag = "bytebeasts-Battle" 6 | manifest_name = "bytebeasts-Battle-55b5860b" 7 | 8 | [[members]] 9 | name = "battle_id" 10 | type = "u32" 11 | key = true 12 | 13 | [[members]] 14 | name = "player_id" 15 | type = "u32" 16 | key = false 17 | 18 | [[members]] 19 | name = "opponent_id" 20 | type = "u32" 21 | key = false 22 | 23 | [[members]] 24 | name = "active_beast_player" 25 | type = "u32" 26 | key = false 27 | 28 | [[members]] 29 | name = "active_beast_opponent" 30 | type = "u32" 31 | key = false 32 | 33 | [[members]] 34 | name = "battle_active" 35 | type = "u32" 36 | key = false 37 | 38 | [[members]] 39 | name = "turn" 40 | type = "u32" 41 | key = false 42 | -------------------------------------------------------------------------------- /manifests/dev/base/models/bytebeasts-LeaderboardEntry-7237950c.toml: -------------------------------------------------------------------------------- 1 | kind = "DojoModel" 2 | class_hash = "0x4f9ca94349981f722e598f396bcca466289aca05dcfb277ef562ee02fee333c" 3 | original_class_hash = "0x4f9ca94349981f722e598f396bcca466289aca05dcfb277ef562ee02fee333c" 4 | abi = "manifests/dev/base/abis/models/bytebeasts-LeaderboardEntry-7237950c.json" 5 | tag = "bytebeasts-LeaderboardEntry" 6 | manifest_name = "bytebeasts-LeaderboardEntry-7237950c" 7 | 8 | [[members]] 9 | name = "player_id" 10 | type = "u32" 11 | key = true 12 | 13 | [[members]] 14 | name = "player_name" 15 | type = "felt252" 16 | key = false 17 | 18 | [[members]] 19 | name = "score" 20 | type = "u32" 21 | key = false 22 | 23 | [[members]] 24 | name = "wins" 25 | type = "u32" 26 | key = false 27 | 28 | [[members]] 29 | name = "losses" 30 | type = "u32" 31 | key = false 32 | 33 | [[members]] 34 | name = "highest_score" 35 | type = "u32" 36 | key = false 37 | 38 | [[members]] 39 | name = "is_active" 40 | type = "bool" 41 | key = false 42 | -------------------------------------------------------------------------------- /manifests/dev/base/models/bytebeasts-Game-e91217d7.toml: -------------------------------------------------------------------------------- 1 | kind = "DojoModel" 2 | class_hash = "0x57c477846284e274054c78c5b265af51f8815abbf0147828080c274b0639764" 3 | original_class_hash = "0x57c477846284e274054c78c5b265af51f8815abbf0147828080c274b0639764" 4 | abi = "manifests/dev/base/abis/models/bytebeasts-Game-e91217d7.json" 5 | tag = "bytebeasts-Game" 6 | manifest_name = "bytebeasts-Game-e91217d7" 7 | 8 | [[members]] 9 | name = "game_id" 10 | type = "u128" 11 | key = true 12 | 13 | [[members]] 14 | name = "player_1" 15 | type = "ContractAddress" 16 | key = false 17 | 18 | [[members]] 19 | name = "player_2" 20 | type = "ContractAddress" 21 | key = false 22 | 23 | [[members]] 24 | name = "player_3" 25 | type = "ContractAddress" 26 | key = false 27 | 28 | [[members]] 29 | name = "player_4" 30 | type = "ContractAddress" 31 | key = false 32 | 33 | [[members]] 34 | name = "status" 35 | type = "GameStatus" 36 | key = false 37 | 38 | [[members]] 39 | name = "is_private" 40 | type = "bool" 41 | key = false 42 | -------------------------------------------------------------------------------- /manifests/dev/base/models/bytebeasts-Tournament-12bdecb1.toml: -------------------------------------------------------------------------------- 1 | kind = "DojoModel" 2 | class_hash = "0x6d38c864554f8be34be3ab85e56ce73c86ad695b61b8ccec9553cf208631d0b" 3 | original_class_hash = "0x6d38c864554f8be34be3ab85e56ce73c86ad695b61b8ccec9553cf208631d0b" 4 | abi = "manifests/dev/base/abis/models/bytebeasts-Tournament-12bdecb1.json" 5 | tag = "bytebeasts-Tournament" 6 | manifest_name = "bytebeasts-Tournament-12bdecb1" 7 | 8 | [[members]] 9 | name = "tournament_id" 10 | type = "u32" 11 | key = true 12 | 13 | [[members]] 14 | name = "name" 15 | type = "felt252" 16 | key = false 17 | 18 | [[members]] 19 | name = "status" 20 | type = "TournamentStatus" 21 | key = false 22 | 23 | [[members]] 24 | name = "entry_fee" 25 | type = "u32" 26 | key = false 27 | 28 | [[members]] 29 | name = "max_participants" 30 | type = "u32" 31 | key = false 32 | 33 | [[members]] 34 | name = "current_participants" 35 | type = "Array" 36 | key = false 37 | 38 | [[members]] 39 | name = "prize_pool" 40 | type = "u32" 41 | key = false 42 | -------------------------------------------------------------------------------- /manifests/dev/base/models/bytebeasts-Achievement-58a03b97.toml: -------------------------------------------------------------------------------- 1 | kind = "DojoModel" 2 | class_hash = "0x41f50347f6f957bc556346a2cdea3f31523f3c25966826e7ca7dea1de185c40" 3 | original_class_hash = "0x41f50347f6f957bc556346a2cdea3f31523f3c25966826e7ca7dea1de185c40" 4 | abi = "manifests/dev/base/abis/models/bytebeasts-Achievement-58a03b97.json" 5 | tag = "bytebeasts-Achievement" 6 | manifest_name = "bytebeasts-Achievement-58a03b97" 7 | 8 | [[members]] 9 | name = "achievement_id" 10 | type = "u64" 11 | key = true 12 | 13 | [[members]] 14 | name = "achievement_type" 15 | type = "AchievementType" 16 | key = false 17 | 18 | [[members]] 19 | name = "rarity" 20 | type = "AchievementRarity" 21 | key = false 22 | 23 | [[members]] 24 | name = "name" 25 | type = "felt252" 26 | key = false 27 | 28 | [[members]] 29 | name = "description" 30 | type = "ByteArray" 31 | key = false 32 | 33 | [[members]] 34 | name = "is_hidden" 35 | type = "bool" 36 | key = false 37 | 38 | [[members]] 39 | name = "is_unlocked" 40 | type = "bool" 41 | key = false 42 | -------------------------------------------------------------------------------- /src/systems/move.cairo: -------------------------------------------------------------------------------- 1 | use bytebeasts::{ 2 | models::{player::Player, coordinates::Coordinates, position::Position}, 3 | }; 4 | 5 | #[dojo::interface] 6 | trait IMoveAction { 7 | fn move(ref world: IWorldDispatcher, player_id: u32, new_x: u32, new_y: u32); 8 | } 9 | 10 | #[dojo::contract] 11 | mod move_action { 12 | use super::IMoveAction; 13 | use starknet::{ContractAddress, get_caller_address}; 14 | use bytebeasts::{ 15 | models::{player::Player, coordinates::Coordinates, position::Position}, 16 | }; 17 | 18 | #[abi(embed_v0)] 19 | impl MoveActionImpl of IMoveAction { 20 | fn move(ref world: IWorldDispatcher, player_id: u32, new_x: u32, new_y: u32) { 21 | let player_from_world = get!(world, player_id, (Player)); 22 | 23 | set!( 24 | world, 25 | ( 26 | Position { 27 | player: player_from_world, coordinates: Coordinates { x: new_x, y: new_y } 28 | }, 29 | ) 30 | ); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Dojo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/models/position.cairo: -------------------------------------------------------------------------------- 1 | use super::coordinates::Coordinates; 2 | use super::player::Player; 3 | 4 | #[derive(Drop, Copy, Serde)] 5 | #[dojo::model] 6 | struct Position { 7 | #[key] 8 | player: Player, 9 | coordinates: Coordinates, 10 | } 11 | 12 | #[cfg(test)] 13 | mod tests { 14 | use bytebeasts::{models::{position::Position, coordinates::Coordinates, player::Player},}; 15 | 16 | #[test] 17 | fn test_position_initialization() { 18 | let player = Player { 19 | player_id: 1, 20 | player_name: 'Hero', 21 | beast_1: 1, 22 | beast_2: 2, 23 | beast_3: 3, 24 | beast_4: 4, 25 | potions: 5, 26 | }; 27 | 28 | let coordinates = Coordinates { x: 10, y: 10, }; 29 | 30 | let position = Position { player: player, coordinates: coordinates }; 31 | 32 | assert_eq!(position.player.player_id, 1, "Player ID should be 1"); 33 | assert_eq!(position.coordinates.x, 10, "Player X coordinate should be 10"); 34 | assert_eq!(position.coordinates.y, 10, "Player Y coordinate should be 10"); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | katana: 2 | katana --disable-fee --allowed-origins "*" --invoke-max-steps 4294967295 3 | 4 | setup: 5 | @./scripts/setup.sh 6 | 7 | init: 8 | @mkdir -p .git/hooks 9 | @touch .git/hooks/pre-push 10 | @echo '#!/bin/bash' > .git/hooks//pre-push 11 | @echo 'echo "Running pre-push hook..."' >> .git/hooks/pre-push 12 | @echo 'echo "Executing sozo test..."' >> .git/hooks/pre-push 13 | @echo '' >> .git/hooks/pre-push 14 | @echo '# Run sozo test' >> .git/hooks/pre-push 15 | @echo 'if ! sozo test; then' >> .git/hooks/pre-push 16 | @echo ' echo "❌ sozo test failed. Push aborted."' >> .git/hooks/pre-push 17 | @echo ' exit 1' >> .git/hooks/pre-push 18 | @echo 'fi' >> .git/hooks/pre-push 19 | @echo '' >> .git/hooks/pre-push 20 | @echo 'echo "✅ sozo test passed. Proceeding with push..."' >> .git/hooks/pre-push 21 | @echo 'exit 0' >> .git/hooks/pre-push 22 | @chmod +x .git/hooks/pre-push 23 | @echo "Git hooks initialized successfully!" 24 | 25 | # Define tasks that are not real files 26 | .PHONY: katana setup torii init 27 | 28 | # Catch-all rule for undefined commands 29 | %: 30 | @echo "Error: Command '$(MAKECMDGOALS)' is not defined." 31 | @exit 1 32 | -------------------------------------------------------------------------------- /manifests/dev/base/models/bytebeasts-GamePlayer-596ef4a1.toml: -------------------------------------------------------------------------------- 1 | kind = "DojoModel" 2 | class_hash = "0x52df62dec799bbf7ba4725f74e32e579dec2d90a7a995638761646157bb7e18" 3 | original_class_hash = "0x52df62dec799bbf7ba4725f74e32e579dec2d90a7a995638761646157bb7e18" 4 | abi = "manifests/dev/base/abis/models/bytebeasts-GamePlayer-596ef4a1.json" 5 | tag = "bytebeasts-GamePlayer" 6 | manifest_name = "bytebeasts-GamePlayer-596ef4a1" 7 | 8 | [[members]] 9 | name = "address" 10 | type = "ContractAddress" 11 | key = true 12 | 13 | [[members]] 14 | name = "game_id" 15 | type = "u128" 16 | key = true 17 | 18 | [[members]] 19 | name = "beast_1" 20 | type = "u8" 21 | key = false 22 | 23 | [[members]] 24 | name = "beast_2" 25 | type = "u8" 26 | key = false 27 | 28 | [[members]] 29 | name = "beast_3" 30 | type = "u8" 31 | key = false 32 | 33 | [[members]] 34 | name = "beast_4" 35 | type = "u8" 36 | key = false 37 | 38 | [[members]] 39 | name = "bag_id" 40 | type = "u8" 41 | key = false 42 | 43 | [[members]] 44 | name = "active_mount" 45 | type = "u8" 46 | key = false 47 | 48 | [[members]] 49 | name = "mounts" 50 | type = "Array" 51 | key = false 52 | 53 | [[members]] 54 | name = "position" 55 | type = "Array" 56 | key = false 57 | -------------------------------------------------------------------------------- /src/models/erc721/models.cairo: -------------------------------------------------------------------------------- 1 | // Starknet imports 2 | 3 | use starknet::ContractAddress; 4 | 5 | #[dojo::model] 6 | #[derive(Copy, Drop, Serde)] 7 | struct ERC721Meta { 8 | #[key] 9 | token: ContractAddress, 10 | name: felt252, 11 | symbol: felt252, 12 | base_uri: felt252, 13 | } 14 | 15 | #[dojo::model] 16 | #[derive(Copy, Drop, Serde)] 17 | struct ERC721OperatorApproval { 18 | #[key] 19 | token: ContractAddress, 20 | #[key] 21 | owner: ContractAddress, 22 | #[key] 23 | operator: ContractAddress, 24 | approved: bool 25 | } 26 | 27 | #[dojo::model] 28 | #[derive(Copy, Drop, Serde)] 29 | struct ERC721Owner { 30 | #[key] 31 | token: ContractAddress, 32 | #[key] 33 | token_id: felt252, 34 | address: ContractAddress 35 | } 36 | 37 | #[dojo::model] 38 | #[derive(Model, Copy, Drop, Serde)] 39 | struct ERC721Balance { 40 | #[key] 41 | token: ContractAddress, 42 | #[key] 43 | account: ContractAddress, 44 | amount: u256, 45 | } 46 | 47 | #[dojo::model] 48 | #[derive(Copy, Drop, Serde)] 49 | struct ERC721TokenApproval { 50 | #[key] 51 | token: ContractAddress, 52 | #[key] 53 | token_id: felt252, 54 | address: ContractAddress, 55 | } 56 | -------------------------------------------------------------------------------- /src/models/bag.cairo: -------------------------------------------------------------------------------- 1 | use super::potion::Potion; 2 | use array::ArrayTrait; 3 | 4 | #[derive(Drop, Serde)] 5 | #[dojo::model] 6 | struct Bag { 7 | #[key] 8 | pub bag_id: u32, 9 | #[key] 10 | pub player_id: u32, 11 | pub max_capacity: u32, 12 | pub potions: Array, 13 | } 14 | 15 | #[cfg(test)] 16 | mod tests { 17 | use bytebeasts::{models::{bag::Bag, potion::Potion}}; 18 | use array::ArrayTrait; 19 | 20 | #[test] 21 | fn test_bag_initialization() { 22 | let mut bag = Bag { 23 | bag_id: 1, 24 | player_id: 1, 25 | max_capacity: 10, 26 | potions: ArrayTrait::new(), 27 | }; 28 | 29 | let potion = Potion { 30 | potion_id: 1, 31 | potion_name: 'Restore everything', 32 | potion_effect: 50, 33 | }; 34 | bag.potions.append(potion); 35 | 36 | assert_eq!(bag.bag_id, 1, "Bag ID should be 1"); 37 | assert_eq!(bag.player_id, 1, "Player ID should be 1"); 38 | assert_eq!(bag.potions.len(), 1, "Bag should have 1 potion"); 39 | assert_eq!(bag.max_capacity, 10, "Bag should have a max capacity of 10"); 40 | assert_eq!(bag.potions.pop_front().unwrap().potion_id, 1, "Bag potion ID should be 1"); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /manifests/dev/base/models/bytebeasts-NPC-4c5239ac.toml: -------------------------------------------------------------------------------- 1 | kind = "DojoModel" 2 | class_hash = "0x3ba44df67a037c20f004b7f5ab7725932d4519eed6beb6bc223a03e96c0f0f9" 3 | original_class_hash = "0x3ba44df67a037c20f004b7f5ab7725932d4519eed6beb6bc223a03e96c0f0f9" 4 | abi = "manifests/dev/base/abis/models/bytebeasts-NPC-4c5239ac.json" 5 | tag = "bytebeasts-NPC" 6 | manifest_name = "bytebeasts-NPC-4c5239ac" 7 | 8 | [[members]] 9 | name = "npc_id" 10 | type = "u32" 11 | key = true 12 | 13 | [[members]] 14 | name = "npc_name" 15 | type = "felt252" 16 | key = false 17 | 18 | [[members]] 19 | name = "npc_description" 20 | type = "felt252" 21 | key = false 22 | 23 | [[members]] 24 | name = "npc_role" 25 | type = "Role" 26 | key = false 27 | 28 | [[members]] 29 | name = "dialogue" 30 | type = "ByteArray" 31 | key = false 32 | 33 | [[members]] 34 | name = "is_active" 35 | type = "bool" 36 | key = false 37 | 38 | [[members]] 39 | name = "location" 40 | type = "Coordinates" 41 | key = false 42 | 43 | [[members]] 44 | name = "importance_level" 45 | type = "u8" 46 | key = false 47 | 48 | [[members]] 49 | name = "mission_status" 50 | type = "MissionStatus" 51 | key = false 52 | 53 | [[members]] 54 | name = "reward" 55 | type = "u16" 56 | key = false 57 | 58 | [[members]] 59 | name = "experience_points" 60 | type = "u16" 61 | key = false 62 | 63 | [[members]] 64 | name = "potions" 65 | type = "Array" 66 | key = false 67 | -------------------------------------------------------------------------------- /src/models/mission_status.cairo: -------------------------------------------------------------------------------- 1 | #[derive(Serde, Copy, Drop, Introspect)] 2 | pub enum MissionStatus { 3 | NotStarted, 4 | InProgress, 5 | Completed, 6 | Failed, 7 | } 8 | 9 | impl MissionStatusIntoFelt252 of Into { 10 | fn into(self: MissionStatus) -> felt252 { 11 | match self { 12 | MissionStatus::NotStarted => 0, 13 | MissionStatus::InProgress => 1, 14 | MissionStatus::Completed => 2, 15 | MissionStatus::Failed => 3, 16 | } 17 | } 18 | } 19 | 20 | #[cfg(test)] 21 | mod tests { 22 | use super::{MissionStatus, MissionStatusIntoFelt252}; 23 | 24 | #[test] 25 | fn test_mission_status_into_felt252() { 26 | // Probar la conversión de cada estado de MissionStatus a felt252 27 | 28 | let not_started = MissionStatus::NotStarted; 29 | let in_progress = MissionStatus::InProgress; 30 | let completed = MissionStatus::Completed; 31 | let failed = MissionStatus::Failed; 32 | 33 | assert_eq!(not_started.into(), 0, "MissionStatus::NotStarted deberia convertirse a 0"); 34 | assert_eq!(in_progress.into(), 1, "MissionStatus::InProgress deberia convertirse a 1"); 35 | assert_eq!(completed.into(), 2, "MissionStatus::Completed deberia convertirse a 2"); 36 | assert_eq!(failed.into(), 3, "MissionStatus::Failed deberia convertirse a 3"); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/models/coordinates.cairo: -------------------------------------------------------------------------------- 1 | #[derive(Drop, Copy, Serde, Introspect)] 2 | struct Coordinates { 3 | x: u32, 4 | y: u32 5 | } 6 | 7 | #[cfg(test)] 8 | mod tests { 9 | use super::Coordinates; 10 | 11 | #[test] 12 | fn test_coordinates_initialization() { 13 | // Crear una instancia de Coordinates 14 | let coord = Coordinates { x: 10, y: 20 }; 15 | 16 | // Verificar que los valores se inicializan correctamente 17 | assert_eq!(coord.x, 10, "El valor de x deberia ser 10"); 18 | assert_eq!(coord.y, 20, "El valor de y deberia ser 20"); 19 | } 20 | 21 | #[test] 22 | fn test_coordinates_equality() { 23 | // Crear dos instancias de Coordinates 24 | let coord1 = Coordinates { x: 5, y: 15 }; 25 | let coord2 = Coordinates { x: 5, y: 15 }; 26 | 27 | // Verificar que dos coordenadas iguales son comparables correctamente 28 | assert_eq!(coord1.x, coord2.x, "Las coordenadas x deberian ser iguales"); 29 | assert_eq!(coord1.y, coord2.y, "Las coordenadas y deberian ser iguales"); 30 | } 31 | 32 | #[test] 33 | fn test_coordinates_copy() { 34 | // Verificar que la estructura puede copiarse correctamente 35 | let coord1 = Coordinates { x: 30, y: 40 }; 36 | let coord2 = coord1; // Como la estructura implementa `Copy`, esto debería funcionar 37 | 38 | assert_eq!(coord2.x, 30, "El valor de x en coord2 deberia ser 30"); 39 | assert_eq!(coord2.y, 40, "El valor de y en coord2 deberia ser 40"); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/models/achievement_rarity.cairo: -------------------------------------------------------------------------------- 1 | #[derive(Serde, Copy, Drop, Introspect, PartialEq)] 2 | pub enum AchievementRarity { 3 | Common, 4 | Uncommon, 5 | Rare, 6 | Epic, 7 | Legendary, 8 | } 9 | 10 | impl AchievementRarityIntoFelt252 of Into { 11 | fn into(self: AchievementRarity) -> felt252 { 12 | match self { 13 | AchievementRarity::Common => 0, 14 | AchievementRarity::Uncommon => 1, 15 | AchievementRarity::Rare => 2, 16 | AchievementRarity::Epic => 3, 17 | AchievementRarity::Legendary => 4, 18 | } 19 | } 20 | } 21 | 22 | 23 | #[cfg(test)] 24 | mod tests { 25 | use super::{AchievementRarity, AchievementRarityIntoFelt252}; 26 | 27 | #[test] 28 | fn test_achievement_rarity_into_felt252() { 29 | 30 | let common = AchievementRarity::Common; 31 | let uncommon = AchievementRarity::Uncommon; 32 | let rare = AchievementRarity::Rare; 33 | let epic = AchievementRarity::Epic; 34 | let legendary = AchievementRarity::Legendary; 35 | 36 | assert_eq!(common.into(), 0, "AchievementRarity::Common deberia convertirse a 0"); 37 | assert_eq!(uncommon.into(), 1, "AchievementRarity::Uncommon deberia convertirse a 1"); 38 | assert_eq!(rare.into(), 2, "AchievementRarity::Rare deberia convertirse a 2"); 39 | assert_eq!(epic.into(), 3, "AchievementRarity::Epic deberia convertirse a 3"); 40 | assert_eq!(legendary.into(), 4, "AchievementRarity::Legendary deberia convertirse a 4"); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/models/world_elements.cairo: -------------------------------------------------------------------------------- 1 | #[derive(Serde, Copy, Drop, Introspect)] 2 | pub enum WorldElements { 3 | Crystal, 4 | Draconic, 5 | Shadow, 6 | Light, 7 | Titanium, 8 | } 9 | 10 | impl WorldElementsIntoFelt252 of Into { 11 | fn into(self: WorldElements) -> felt252 { 12 | match self { 13 | WorldElements::Crystal => 0, 14 | WorldElements::Draconic => 1, 15 | WorldElements::Shadow => 2, 16 | WorldElements::Light => 3, 17 | WorldElements::Titanium => 4, 18 | } 19 | } 20 | } 21 | 22 | #[cfg(test)] 23 | mod tests { 24 | use super::WorldElements; 25 | 26 | #[test] 27 | fn test_world_elements_to_felt252() { 28 | // Verificar que cada variante de WorldElements se convierta correctamente en el valor felt252 esperado 29 | let crystal: felt252 = WorldElements::Crystal.into(); 30 | let draconic: felt252 = WorldElements::Draconic.into(); 31 | let shadow: felt252 = WorldElements::Shadow.into(); 32 | let light: felt252 = WorldElements::Light.into(); 33 | let titanium: felt252 = WorldElements::Titanium.into(); 34 | 35 | // Comprobar los valores 36 | assert_eq!(crystal, 0, "Crystal deberia convertirse a 0"); 37 | assert_eq!(draconic, 1, "Draconic deberia convertirse a 1"); 38 | assert_eq!(shadow, 2, "Shadow deberia convertirse a 2"); 39 | assert_eq!(light, 3, "Light deberia convertirse a 3"); 40 | assert_eq!(titanium, 4, "Titanium deberia convertirse a 4"); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /manifests/dev/base/models/bytebeasts-Beast-27809d20.toml: -------------------------------------------------------------------------------- 1 | kind = "DojoModel" 2 | class_hash = "0x7bef5c17e52dab476cd7ae664bbb0f0024aae955ed8b12592e2d6faf7ff6a3c" 3 | original_class_hash = "0x7bef5c17e52dab476cd7ae664bbb0f0024aae955ed8b12592e2d6faf7ff6a3c" 4 | abi = "manifests/dev/base/abis/models/bytebeasts-Beast-27809d20.json" 5 | tag = "bytebeasts-Beast" 6 | manifest_name = "bytebeasts-Beast-27809d20" 7 | 8 | [[members]] 9 | name = "beast_id" 10 | type = "u32" 11 | key = true 12 | 13 | [[members]] 14 | name = "beast_name" 15 | type = "felt252" 16 | key = false 17 | 18 | [[members]] 19 | name = "beast_type" 20 | type = "WorldElements" 21 | key = false 22 | 23 | [[members]] 24 | name = "beast_description" 25 | type = "felt252" 26 | key = false 27 | 28 | [[members]] 29 | name = "player_id" 30 | type = "u32" 31 | key = false 32 | 33 | [[members]] 34 | name = "hp" 35 | type = "u32" 36 | key = false 37 | 38 | [[members]] 39 | name = "current_hp" 40 | type = "u32" 41 | key = false 42 | 43 | [[members]] 44 | name = "attack" 45 | type = "u32" 46 | key = false 47 | 48 | [[members]] 49 | name = "defense" 50 | type = "u32" 51 | key = false 52 | 53 | [[members]] 54 | name = "mt1" 55 | type = "u32" 56 | key = false 57 | 58 | [[members]] 59 | name = "mt2" 60 | type = "u32" 61 | key = false 62 | 63 | [[members]] 64 | name = "mt3" 65 | type = "u32" 66 | key = false 67 | 68 | [[members]] 69 | name = "mt4" 70 | type = "u32" 71 | key = false 72 | 73 | [[members]] 74 | name = "level" 75 | type = "u32" 76 | key = false 77 | 78 | [[members]] 79 | name = "experience_to_next_level" 80 | type = "u64" 81 | key = false 82 | -------------------------------------------------------------------------------- /src/models/beast.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | use super::world_elements::WorldElements; 3 | 4 | #[derive(Copy, Drop, Serde)] 5 | #[dojo::model] 6 | pub struct Beast { 7 | #[key] 8 | pub beast_id: u32, 9 | pub beast_name: felt252, 10 | pub beast_type: WorldElements, 11 | pub beast_description: felt252, 12 | pub player_id: u32, 13 | pub hp: u32, 14 | pub current_hp: u32, 15 | pub attack: u32, 16 | pub defense: u32, 17 | pub mt1: u32, 18 | pub mt2: u32, 19 | pub mt3: u32, 20 | pub mt4: u32, 21 | pub level: u32, 22 | pub experience_to_next_level: u64, 23 | } 24 | 25 | 26 | #[generate_trait] 27 | impl BeastImpl of BeastTrait { 28 | fn exist(self: Beast) -> bool { 29 | self.hp > 0 30 | } 31 | } 32 | 33 | #[cfg(test)] 34 | mod tests { 35 | use bytebeasts::{models::{beast::{Beast, BeastTrait}, world_elements::WorldElements},}; 36 | 37 | #[test] 38 | fn test_beast_exist() { 39 | let beast = Beast { 40 | beast_id: 1, 41 | beast_name: 0, 42 | beast_type: WorldElements::Crystal, 43 | beast_description: 0, 44 | player_id: 1, 45 | hp: 100, 46 | current_hp: 100, 47 | attack: 50, 48 | defense: 40, 49 | mt1: 1, // Fire Blast 50 | mt2: 2, // Ember 51 | mt3: 3, // Flame Wheel 52 | mt4: 4, // Fire Punch 53 | level: 5, 54 | experience_to_next_level: 1000, 55 | }; 56 | assert(beast.exist(), 'Beast is alive'); 57 | assert_eq!(beast.hp, 100, "HP should be initialized to 100"); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /.github/mark-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /.github/mark-light.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/models/battle.cairo: -------------------------------------------------------------------------------- 1 | // Defines the `Battle` Model, which represents a battle between two players. 2 | // Includes various fields to track the state and progress of the battle. 3 | #[derive(Copy, Drop, Serde)] 4 | #[dojo::model] 5 | pub struct Battle { 6 | // Unique identifier for the battle. 7 | #[key] 8 | pub battle_id: u32, 9 | 10 | // ID of the player involved in the battle. 11 | pub player_id: u32, 12 | 13 | // ID of the opponent involved in the battle. 14 | pub opponent_id: u32, 15 | 16 | // ID of the active beast for the player. 17 | pub active_beast_player: u32, 18 | 19 | // ID of the active beast for the opponent. 20 | pub active_beast_opponent: u32, 21 | 22 | // Flag to indicate if the battle is currently active (1 for active, 0 for inactive). 23 | pub battle_active: u32, 24 | 25 | // Current turn number in the battle. 26 | pub turn: u32, 27 | } 28 | 29 | 30 | #[cfg(test)] 31 | mod tests { 32 | 33 | use bytebeasts::{models::{battle::Battle},}; 34 | 35 | 36 | 37 | #[test] 38 | fn test_battle_initialization() { 39 | let battle = Battle { 40 | battle_id: 1, 41 | player_id: 1, 42 | opponent_id: 2, 43 | active_beast_player: 1, 44 | active_beast_opponent: 2, 45 | battle_active: 1, 46 | turn: 1, 47 | }; 48 | 49 | assert_eq!(battle.battle_id, 1, "Battle ID should be 1"); 50 | assert_eq!(battle.player_id, 1, "Player ID should be 1"); 51 | assert_eq!(battle.opponent_id, 2, "Opponent ID should be 2"); 52 | assert_eq!(battle.battle_active, 1, "Battle should be active"); 53 | assert_eq!(battle.turn, 1, "Turn should be 1"); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/systems/bag.cairo: -------------------------------------------------------------------------------- 1 | use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; 2 | use bytebeasts::{ 3 | models::{player::Player, potion::Potion, bag::Bag}, 4 | }; 5 | 6 | #[dojo::interface] 7 | trait IBagAction { 8 | fn init_bag(ref world: IWorldDispatcher, bag_id: u32, player_id: u32); 9 | fn add_item(ref world: IWorldDispatcher, player_id: u32, bag_id: u32, potion: Potion); 10 | fn take_out_item(ref world: IWorldDispatcher, player_id: u32, bag_id: u32) -> Potion; 11 | } 12 | 13 | #[dojo::contract] 14 | mod bag_system { 15 | use super::IBagAction; 16 | use array::ArrayTrait; 17 | use bytebeasts::{ 18 | models::{player::Player, potion::Potion, bag::Bag}, 19 | }; 20 | 21 | const MAX_BAG_SIZE: usize = 10; 22 | 23 | #[abi(embed_v0)] 24 | impl BagActionImpl of IBagAction { 25 | fn init_bag(ref world: IWorldDispatcher, bag_id: u32, player_id: u32) { 26 | let bag = Bag { 27 | bag_id: bag_id, 28 | player_id: player_id, 29 | max_capacity: MAX_BAG_SIZE, 30 | potions: ArrayTrait::new(), 31 | }; 32 | 33 | set!(world, (bag)) 34 | } 35 | 36 | fn add_item(ref world: IWorldDispatcher, player_id: u32, bag_id: u32, potion: Potion) { 37 | let mut bag = get!(world, (bag_id, player_id), (Bag)); 38 | bag.potions.append(potion); 39 | set!(world, (bag)); 40 | } 41 | 42 | fn take_out_item(ref world: IWorldDispatcher, player_id: u32, bag_id: u32) -> Potion { 43 | let mut bag = get!(world, (bag_id, player_id), (Bag)); 44 | let potion = bag.potions.pop_front().unwrap(); 45 | set!(world, (bag)); 46 | return potion; 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /src/models/tournament.cairo: -------------------------------------------------------------------------------- 1 | #[derive(Serde, Copy, Drop, Introspect, PartialEq, Debug)] 2 | pub enum TournamentStatus { 3 | Pending, 4 | Ongoing, 5 | Completed, 6 | } 7 | 8 | 9 | #[derive(Drop, Serde)] 10 | #[dojo::model] 11 | pub struct Tournament { 12 | #[key] 13 | pub tournament_id: u32, 14 | pub name: felt252, 15 | pub status: TournamentStatus, 16 | pub entry_fee: u32, 17 | pub max_participants: u32, 18 | pub current_participants: Array, 19 | pub prize_pool: u32, 20 | } 21 | 22 | 23 | #[cfg(test)] 24 | mod tests { 25 | use bytebeasts::{ 26 | models::{tournament::Tournament, tournament::TournamentStatus} 27 | }; 28 | 29 | 30 | #[test] 31 | fn test_tournament_initialization() { 32 | let tournament = Tournament { 33 | tournament_id: 1, 34 | name: 'gersonwashere', 35 | status: TournamentStatus::Pending, 36 | entry_fee: 1, 37 | max_participants: 2, 38 | current_participants: array![1], 39 | prize_pool: 1, 40 | }; 41 | 42 | assert_eq!(tournament.tournament_id, 1, "Tournament ID should be 1"); 43 | assert_eq!(tournament.name, 'gersonwashere', "Tournament name should be gersonwashere"); 44 | assert_eq!( 45 | tournament.status, TournamentStatus::Pending, "Tournament status should be pending" 46 | ); 47 | assert_eq!(tournament.entry_fee, 1, "Tournament entry fee should be 1"); 48 | assert_eq!(tournament.max_participants, 2, "Tournament max participants should be 2"); 49 | assert_eq!( 50 | tournament.current_participants.len(), 1, "Tournament current participants should be 1" 51 | ); 52 | assert_eq!(tournament.prize_pool, 1, "Tournament prize pool should be 1"); 53 | } 54 | } 55 | 56 | -------------------------------------------------------------------------------- /Scarb.lock: -------------------------------------------------------------------------------- 1 | # Code generated by scarb DO NOT EDIT. 2 | version = 1 3 | 4 | [[package]] 5 | name = "alexandria_data_structures" 6 | version = "0.2.0" 7 | source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.6.0#946e6e2f9d390ad9f345882a352c0dd6f02ef3ad" 8 | dependencies = [ 9 | "alexandria_encoding", 10 | ] 11 | 12 | [[package]] 13 | name = "alexandria_encoding" 14 | version = "0.1.0" 15 | source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.6.0#946e6e2f9d390ad9f345882a352c0dd6f02ef3ad" 16 | dependencies = [ 17 | "alexandria_math", 18 | "alexandria_numeric", 19 | ] 20 | 21 | [[package]] 22 | name = "alexandria_math" 23 | version = "0.2.0" 24 | source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.6.0#946e6e2f9d390ad9f345882a352c0dd6f02ef3ad" 25 | dependencies = [ 26 | "alexandria_data_structures", 27 | ] 28 | 29 | [[package]] 30 | name = "alexandria_numeric" 31 | version = "0.1.0" 32 | source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.6.0#946e6e2f9d390ad9f345882a352c0dd6f02ef3ad" 33 | dependencies = [ 34 | "alexandria_math", 35 | ] 36 | 37 | [[package]] 38 | name = "alexandria_sorting" 39 | version = "0.1.0" 40 | source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.6.0#946e6e2f9d390ad9f345882a352c0dd6f02ef3ad" 41 | dependencies = [ 42 | "alexandria_data_structures", 43 | ] 44 | 45 | [[package]] 46 | name = "bytebeasts" 47 | version = "0.1.0" 48 | dependencies = [ 49 | "alexandria_sorting", 50 | "dojo", 51 | ] 52 | 53 | [[package]] 54 | name = "dojo" 55 | version = "1.0.0-alpha.4" 56 | source = "git+https://github.com/dojoengine/dojo?tag=v1.0.0-alpha.5#6878242e120d3135d3bc1bb94135d7135693069b" 57 | dependencies = [ 58 | "dojo_plugin", 59 | ] 60 | 61 | [[package]] 62 | name = "dojo_plugin" 63 | version = "1.0.0-alpha.4" 64 | source = "git+https://github.com/dojoengine/dojo?rev=f15def33#f15def330c0d099e79351d11c197f63e8cc1ff36" 65 | -------------------------------------------------------------------------------- /src/tests/test_bag.cairo: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests { 3 | use starknet::ContractAddress; 4 | 5 | use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; 6 | use dojo::utils::test::{spawn_test_world, deploy_contract}; 7 | 8 | use bytebeasts::{ 9 | systems::{bag::{bag_system, IBagActionDispatcher, IBagActionDispatcherTrait}}, 10 | }; 11 | 12 | use bytebeasts::{ 13 | models::bag::{{Bag, bag}}, 14 | models::player::{{Player, player}}, 15 | models::potion::{{Potion, potion}}, 16 | }; 17 | 18 | 19 | // Helper function 20 | // This function create the world and define the required models 21 | #[test] 22 | fn setup_world() -> (IWorldDispatcher, IBagActionDispatcher) { 23 | let mut models = array![ 24 | bag::TEST_CLASS_HASH, 25 | player::TEST_CLASS_HASH, 26 | potion::TEST_CLASS_HASH, 27 | 28 | ]; 29 | 30 | let world = spawn_test_world("bytebeasts", models); 31 | 32 | let contract_address = world.deploy_contract('salt', bag_system::TEST_CLASS_HASH.try_into().unwrap()); 33 | 34 | let bag_system = IBagActionDispatcher { contract_address }; 35 | 36 | world.grant_writer(dojo::utils::bytearray_hash(@"bytebeasts"), contract_address); 37 | 38 | (world, bag_system) 39 | } 40 | 41 | 42 | #[test] 43 | fn test_setup_player_bag() -> (IWorldDispatcher, IBagActionDispatcher) { 44 | let (world, bag_system) = setup_world(); 45 | 46 | let player_ash = Player { 47 | player_id: 1, 48 | player_name: 'Ash', 49 | beast_1: 1, // Beast 1 assigned 50 | beast_2: 0, // No beast assigned 51 | beast_3: 0, // No beast assigned 52 | beast_4: 0, // No beast assigned 53 | potions: 2 54 | }; 55 | 56 | let bag = Bag { 57 | bag_id: 1, 58 | player_id: 1, 59 | max_capacity: 10, 60 | potions: ArrayTrait::new(), 61 | }; 62 | 63 | set!(world,(player_ash)); 64 | 65 | set!(world,(bag)); 66 | 67 | (world, bag_system) 68 | } 69 | 70 | #[test] 71 | fn test_setup() { 72 | let (_, _,) = setup_world(); 73 | let (_, _,) = test_setup_player_bag(); 74 | 75 | } 76 | } -------------------------------------------------------------------------------- /src/models/game_id.cairo: -------------------------------------------------------------------------------- 1 | #[derive(Copy, Drop, Serde)] 2 | #[dojo::model] 3 | pub struct GameId { 4 | #[key] 5 | pub id: u32, 6 | pub game_id: u128 7 | } 8 | 9 | #[cfg(test)] 10 | mod tests { 11 | use super::GameId; 12 | 13 | #[test] 14 | fn test_game_id_initialization() { 15 | // Crear una instancia de GameId 16 | let game_id = GameId { id: 1, game_id: 12345678901234567890123456789012 }; 17 | 18 | // Verificar que los valores se inicializan correctamente 19 | assert_eq!(game_id.id, 1, "El valor de id deberia ser 1"); 20 | assert_eq!(game_id.game_id, 12345678901234567890123456789012, "El valor de game_id deberia ser el esperado"); 21 | } 22 | 23 | #[test] 24 | fn test_game_id_equality() { 25 | // Crear dos instancias de GameId con los mismos valores 26 | let game_id1 = GameId { id: 2, game_id: 98765432109876543210987654321098 }; 27 | let game_id2 = GameId { id: 2, game_id: 98765432109876543210987654321098 }; 28 | 29 | // Verificar que las instancias con los mismos valores son iguales 30 | assert_eq!(game_id1.id, game_id2.id, "Los valores de id deberian ser iguales"); 31 | assert_eq!(game_id1.game_id, game_id2.game_id, "Los valores de game_id deberian ser iguales"); 32 | } 33 | 34 | #[test] 35 | fn test_game_id_copy() { 36 | // Verificar que la estructura puede copiarse correctamente 37 | let game_id1 = GameId { id: 3, game_id: 11111111111111111111111111111111 }; 38 | let game_id2 = game_id1; // Como la estructura implementa `Copy`, esto debería funcionar 39 | 40 | assert_eq!(game_id2.id, 3, "El valor de id en game_id2 deberia ser 3"); 41 | assert_eq!(game_id2.game_id, 11111111111111111111111111111111, "El valor de game_id en game_id2 deberia ser el esperado"); 42 | } 43 | 44 | #[test] 45 | fn test_game_id_invalid() { 46 | // Crear una instancia con un valor de id inesperado 47 | let game_id = GameId { id: 0, game_id: 12345678901234567890123456789012 }; 48 | 49 | // Verificar que no cumple ciertas condiciones (puedes adaptar según la lógica de tu aplicación) 50 | assert_ne!(game_id.id, 1, "El valor de id no deberia ser 1"); 51 | assert_eq!(game_id.game_id, 12345678901234567890123456789012, "El valor de game_id deberia ser el esperado"); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /manifests/dev/base/abis/dojo-base.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "impl", 4 | "name": "WorldProviderImpl", 5 | "interface_name": "dojo::world::world_contract::IWorldProvider" 6 | }, 7 | { 8 | "type": "struct", 9 | "name": "dojo::world::world_contract::IWorldDispatcher", 10 | "members": [ 11 | { 12 | "name": "contract_address", 13 | "type": "core::starknet::contract_address::ContractAddress" 14 | } 15 | ] 16 | }, 17 | { 18 | "type": "interface", 19 | "name": "dojo::world::world_contract::IWorldProvider", 20 | "items": [ 21 | { 22 | "type": "function", 23 | "name": "world", 24 | "inputs": [], 25 | "outputs": [ 26 | { 27 | "type": "dojo::world::world_contract::IWorldDispatcher" 28 | } 29 | ], 30 | "state_mutability": "view" 31 | } 32 | ] 33 | }, 34 | { 35 | "type": "impl", 36 | "name": "UpgradableImpl", 37 | "interface_name": "dojo::contract::upgradeable::IUpgradeable" 38 | }, 39 | { 40 | "type": "interface", 41 | "name": "dojo::contract::upgradeable::IUpgradeable", 42 | "items": [ 43 | { 44 | "type": "function", 45 | "name": "upgrade", 46 | "inputs": [ 47 | { 48 | "name": "new_class_hash", 49 | "type": "core::starknet::class_hash::ClassHash" 50 | } 51 | ], 52 | "outputs": [], 53 | "state_mutability": "external" 54 | } 55 | ] 56 | }, 57 | { 58 | "type": "constructor", 59 | "name": "constructor", 60 | "inputs": [] 61 | }, 62 | { 63 | "type": "event", 64 | "name": "dojo::contract::upgradeable::upgradeable::Upgraded", 65 | "kind": "struct", 66 | "members": [ 67 | { 68 | "name": "class_hash", 69 | "type": "core::starknet::class_hash::ClassHash", 70 | "kind": "data" 71 | } 72 | ] 73 | }, 74 | { 75 | "type": "event", 76 | "name": "dojo::contract::upgradeable::upgradeable::Event", 77 | "kind": "enum", 78 | "variants": [ 79 | { 80 | "name": "Upgraded", 81 | "type": "dojo::contract::upgradeable::upgradeable::Upgraded", 82 | "kind": "nested" 83 | } 84 | ] 85 | }, 86 | { 87 | "type": "event", 88 | "name": "dojo::contract::base_contract::base::Event", 89 | "kind": "enum", 90 | "variants": [ 91 | { 92 | "name": "UpgradeableEvent", 93 | "type": "dojo::contract::upgradeable::upgradeable::Event", 94 | "kind": "flat" 95 | } 96 | ] 97 | } 98 | ] -------------------------------------------------------------------------------- /manifests/dev/deployment/abis/dojo-base.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "impl", 4 | "name": "WorldProviderImpl", 5 | "interface_name": "dojo::world::world_contract::IWorldProvider" 6 | }, 7 | { 8 | "type": "struct", 9 | "name": "dojo::world::world_contract::IWorldDispatcher", 10 | "members": [ 11 | { 12 | "name": "contract_address", 13 | "type": "core::starknet::contract_address::ContractAddress" 14 | } 15 | ] 16 | }, 17 | { 18 | "type": "interface", 19 | "name": "dojo::world::world_contract::IWorldProvider", 20 | "items": [ 21 | { 22 | "type": "function", 23 | "name": "world", 24 | "inputs": [], 25 | "outputs": [ 26 | { 27 | "type": "dojo::world::world_contract::IWorldDispatcher" 28 | } 29 | ], 30 | "state_mutability": "view" 31 | } 32 | ] 33 | }, 34 | { 35 | "type": "impl", 36 | "name": "UpgradableImpl", 37 | "interface_name": "dojo::contract::upgradeable::IUpgradeable" 38 | }, 39 | { 40 | "type": "interface", 41 | "name": "dojo::contract::upgradeable::IUpgradeable", 42 | "items": [ 43 | { 44 | "type": "function", 45 | "name": "upgrade", 46 | "inputs": [ 47 | { 48 | "name": "new_class_hash", 49 | "type": "core::starknet::class_hash::ClassHash" 50 | } 51 | ], 52 | "outputs": [], 53 | "state_mutability": "external" 54 | } 55 | ] 56 | }, 57 | { 58 | "type": "constructor", 59 | "name": "constructor", 60 | "inputs": [] 61 | }, 62 | { 63 | "type": "event", 64 | "name": "dojo::contract::upgradeable::upgradeable::Upgraded", 65 | "kind": "struct", 66 | "members": [ 67 | { 68 | "name": "class_hash", 69 | "type": "core::starknet::class_hash::ClassHash", 70 | "kind": "data" 71 | } 72 | ] 73 | }, 74 | { 75 | "type": "event", 76 | "name": "dojo::contract::upgradeable::upgradeable::Event", 77 | "kind": "enum", 78 | "variants": [ 79 | { 80 | "name": "Upgraded", 81 | "type": "dojo::contract::upgradeable::upgradeable::Upgraded", 82 | "kind": "nested" 83 | } 84 | ] 85 | }, 86 | { 87 | "type": "event", 88 | "name": "dojo::contract::base_contract::base::Event", 89 | "kind": "enum", 90 | "variants": [ 91 | { 92 | "name": "UpgradeableEvent", 93 | "type": "dojo::contract::upgradeable::upgradeable::Event", 94 | "kind": "flat" 95 | } 96 | ] 97 | } 98 | ] -------------------------------------------------------------------------------- /src/systems/realms.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; 3 | 4 | use bytebeasts::{models::{ 5 | game_id::GameId, 6 | game::GameStatus, 7 | game::Game, 8 | game::GameTrait, 9 | game_player::GamePlayer, 10 | game_player::GamePlayerTrait 11 | }}; 12 | 13 | #[dojo::interface] 14 | trait IActions { 15 | fn create_initial_game_id(ref world: IWorldDispatcher); 16 | fn create_game(ref world: IWorldDispatcher) -> Game; 17 | fn join_game(ref world: IWorldDispatcher, game_id: u128, player_2_address: ContractAddress); 18 | } 19 | 20 | #[dojo::contract] 21 | mod actions { 22 | use starknet::{ContractAddress, get_caller_address, SyscallResultTrait}; 23 | use starknet::{get_tx_info, get_block_number}; 24 | use bytebeasts::{ 25 | models::{ 26 | game_id::GameId, 27 | game::GameStatus, 28 | game::Game, 29 | game::GameTrait, 30 | game_player::GamePlayer, 31 | game_player::GamePlayerTrait 32 | }, 33 | }; 34 | 35 | use super::IActions; 36 | 37 | #[abi(embed_v0)] 38 | impl ActionsImpl of IActions { 39 | fn create_initial_game_id(ref world: IWorldDispatcher) { 40 | let existing_game_id = get!(world, 1, (GameId)); 41 | if (existing_game_id.game_id > 0) { 42 | panic!("error global game id already created"); 43 | } 44 | let game_id: GameId = GameId { id: 1, game_id: 1 }; 45 | set!(world, (game_id)); 46 | } 47 | 48 | fn create_game(ref world: IWorldDispatcher) -> Game { 49 | let player_1_address = get_caller_address(); 50 | let mut game_id: GameId = get!(world, 1, (GameId)); 51 | let player_1 = GamePlayerTrait::new(game_id.game_id, player_1_address); 52 | let game: Game = GameTrait::new(game_id.game_id, player_1_address); 53 | game_id.game_id += 1; 54 | set!(world, (player_1, game, game_id)); 55 | game 56 | } 57 | 58 | fn join_game( 59 | ref world: IWorldDispatcher, game_id: u128, player_2_address: ContractAddress 60 | ) { 61 | let mut game = get!(world, game_id, (Game)); 62 | assert!( 63 | game.player_2 == core::num::traits::Zero::::zero(), 64 | "player_2 already set" 65 | ); 66 | let player_2 = GamePlayerTrait::new(game.game_id, player_2_address); 67 | game.join_game(player_2); 68 | let player_2 = GamePlayerTrait::new(game.game_id, player_2_address); 69 | set!(world, (player_2, game)); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/models/erc20/interface.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | #[starknet::interface] 4 | trait IERC20 { 5 | fn total_supply(self: @TState) -> u256; 6 | fn balance_of(self: @TState, account: ContractAddress) -> u256; 7 | fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256; 8 | fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool; 9 | fn transfer_from( 10 | ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256 11 | ) -> bool; 12 | fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool; 13 | } 14 | 15 | #[starknet::interface] 16 | trait IERC20Metadata { 17 | fn name(self: @TState) -> felt252; 18 | fn symbol(self: @TState) -> felt252; 19 | fn decimals(self: @TState) -> u8; 20 | } 21 | 22 | #[starknet::interface] 23 | trait IERC20Camel { 24 | fn totalSupply(self: @TState) -> u256; 25 | fn balanceOf(self: @TState, account: ContractAddress) -> u256; 26 | fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256; 27 | fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool; 28 | fn transferFrom( 29 | ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256 30 | ) -> bool; 31 | fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool; 32 | } 33 | 34 | #[starknet::interface] 35 | trait IERC20CamelOnly { 36 | fn totalSupply(self: @TState) -> u256; 37 | fn balanceOf(self: @TState, account: ContractAddress) -> u256; 38 | fn transferFrom( 39 | ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256 40 | ) -> bool; 41 | } 42 | 43 | #[starknet::interface] 44 | trait ERC20ABI { 45 | // IERC20 46 | fn total_supply(self: @TState) -> u256; 47 | fn balance_of(self: @TState, account: ContractAddress) -> u256; 48 | fn allowance(self: @TState, owner: ContractAddress, spender: ContractAddress) -> u256; 49 | fn transfer(ref self: TState, recipient: ContractAddress, amount: u256) -> bool; 50 | fn transfer_from( 51 | ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256 52 | ) -> bool; 53 | fn approve(ref self: TState, spender: ContractAddress, amount: u256) -> bool; 54 | 55 | // IERC20Metadata 56 | fn name(self: @TState) -> felt252; 57 | fn symbol(self: @TState) -> felt252; 58 | fn decimals(self: @TState) -> u8; 59 | 60 | // IERC20CamelOnly 61 | fn totalSupply(self: @TState) -> u256; 62 | fn balanceOf(self: @TState, account: ContractAddress) -> u256; 63 | fn transferFrom( 64 | ref self: TState, sender: ContractAddress, recipient: ContractAddress, amount: u256 65 | ) -> bool; 66 | } 67 | -------------------------------------------------------------------------------- /src/models/game_player.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | #[derive(Drop, Serde, Debug)] 4 | #[dojo::model] 5 | pub struct GamePlayer { 6 | #[key] 7 | pub address: ContractAddress, 8 | #[key] 9 | pub game_id: u128, 10 | pub beast_1: u8, 11 | pub beast_2: u8, 12 | pub beast_3: u8, 13 | pub beast_4: u8, 14 | pub bag_id: u8, 15 | pub active_mount: u8, 16 | pub mounts: Array, 17 | pub position: Array 18 | } 19 | 20 | pub trait GamePlayerTrait { 21 | fn new(game_id: u128, address: ContractAddress) -> GamePlayer; 22 | } 23 | 24 | impl GamePlayerImpl of GamePlayerTrait { 25 | // logic to create an instance of a game player 26 | fn new(game_id: u128, address: ContractAddress) -> GamePlayer { 27 | let game_player = GamePlayer { 28 | address: address, 29 | game_id: game_id, 30 | beast_1: 0_u8, 31 | beast_2: 0_u8, 32 | beast_3: 0_u8, 33 | beast_4: 0_u8, 34 | bag_id: 0_u8, 35 | active_mount: 0_u8, 36 | mounts: ArrayTrait::new(), 37 | position: ArrayTrait::new(), 38 | }; 39 | game_player 40 | } 41 | } 42 | 43 | #[cfg(test)] 44 | mod tests { 45 | use bytebeasts::{models::{game_player::GamePlayer, game_player::GamePlayerTrait}}; 46 | use starknet::{ContractAddress, get_caller_address, SyscallResultTrait}; 47 | 48 | #[test] 49 | fn test_game_player_initialization() { 50 | // Crear una dirección de contrato de prueba 51 | let address = get_caller_address(); 52 | let game_id = 98765432101234567890123456789012_u128; 53 | 54 | // Crear un jugador usando el método `new` 55 | let mut game_player = GamePlayerTrait::new(game_id, address); 56 | 57 | // Verificar que los campos se inicializan correctamente 58 | assert_eq!(game_player.address, address, "La direccion deberia ser la esperada"); 59 | assert_eq!(game_player.game_id, game_id, "El game_id deberia ser el esperado"); 60 | assert_eq!(game_player.beast_1, 0_u8, "El beast_1 deberia inicializarse en 0"); 61 | assert_eq!(game_player.beast_2, 0_u8, "El beast_2 deberia inicializarse en 0"); 62 | assert_eq!(game_player.beast_3, 0_u8, "El beast_3 deberia inicializarse en 0"); 63 | assert_eq!(game_player.beast_4, 0_u8, "El beast_4 deberia inicializarse en 0"); 64 | assert_eq!(game_player.bag_id, 0_u8, "El bag_id deberia inicializarse en 0"); 65 | assert_eq!(game_player.active_mount, 0_u8, "El active_mount deberia inicializarse en 0"); 66 | 67 | // Verificar que los arrays de mounts y position estén vacíos al inicio 68 | assert!(game_player.mounts.is_empty(), "El array de mounts deberia estar vacio"); 69 | assert!(game_player.position.is_empty(), "El array de position deberia estar vacio"); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/models/achievement_type.cairo: -------------------------------------------------------------------------------- 1 | #[derive(Serde, Copy, Drop, Introspect, PartialEq)] 2 | pub enum AchievementType { 3 | FirstWin, 4 | TenWins, 5 | HundredWins, 6 | FirstBeast, 7 | TenBeasts, 8 | RareBeast, 9 | FirstNPCInteraction, 10 | RandomBattleChampion, 11 | BeastMaster, 12 | LegendaryPlayer, 13 | TopScorer, 14 | } 15 | 16 | impl AchievementTypeIntoFelt252 of Into { 17 | fn into(self: AchievementType) -> felt252 { 18 | match self { 19 | AchievementType::FirstWin => 0, 20 | AchievementType::TenWins => 1, 21 | AchievementType::HundredWins => 2, 22 | AchievementType::FirstBeast => 3, 23 | AchievementType::TenBeasts => 4, 24 | AchievementType::RareBeast => 5, 25 | AchievementType::FirstNPCInteraction => 6, 26 | AchievementType::RandomBattleChampion => 7, 27 | AchievementType::BeastMaster => 8, 28 | AchievementType::LegendaryPlayer => 9, 29 | AchievementType::TopScorer => 10, 30 | } 31 | } 32 | } 33 | 34 | #[cfg(test)] 35 | mod tests { 36 | use super::{AchievementType, AchievementTypeIntoFelt252}; 37 | 38 | #[test] 39 | fn test_achievement_type_into_felt252() { 40 | 41 | let first_win = AchievementType::FirstWin; 42 | let ten_wins = AchievementType::TenWins; 43 | let hundred_wins = AchievementType::HundredWins; 44 | let first_beast = AchievementType::FirstBeast; 45 | let ten_beast = AchievementType::TenBeasts; 46 | let rare_beast = AchievementType::RareBeast; 47 | let first_npc_interaction = AchievementType::FirstNPCInteraction; 48 | let random_battle = AchievementType::RandomBattleChampion; 49 | let beast_master = AchievementType::BeastMaster; 50 | let legendary_player = AchievementType::LegendaryPlayer; 51 | let top_scorer = AchievementType::TopScorer; 52 | 53 | assert_eq!(first_win.into(), 0, "AchievementType::FirstWin deberia convertirse a 0"); 54 | assert_eq!(ten_wins.into(), 1, "AchievementType::TenWins deberia convertirse a 1"); 55 | assert_eq!(hundred_wins.into(), 2, "AchievementType::HundredWins deberia convertirse a 2"); 56 | assert_eq!(first_beast.into(), 3, "AchievementType::FirstBeast deberia convertirse a 3"); 57 | assert_eq!(ten_beast.into(), 4, "AchievementType::TenBeasts deberia convertirse a 4"); 58 | assert_eq!(rare_beast.into(), 5, "AchievementType::RareBeast deberia convertirse a 5"); 59 | assert_eq!(first_npc_interaction.into(), 6, "AchievementType::FirstNPCInteraction deberia convertirse a 6"); 60 | assert_eq!(random_battle.into(), 7, "AchievementType::RandomBattleChampion deberia convertirse a 7"); 61 | assert_eq!(beast_master.into(), 8, "AchievementType::BeastMaster deberia convertirse a 8"); 62 | assert_eq!(legendary_player.into(), 9, "AchievementType::LegendaryPlayer deberia convertirse a 9"); 63 | assert_eq!(top_scorer.into(), 10, "AchievementType::TopScorer deberia convertirse a 10"); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /docs/contribution/CONTRIBUTION.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ByteBeats official logo 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | [![Telegram Chat][tg-badge]][tg-url] 16 | 17 | [tg-badge]: https://img.shields.io/endpoint?color=neon&logo=telegram&label=chat&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fdojoengine 18 | [tg-url]: https://t.me/+-84e2pqLtqNkZDAx 19 | 20 | 21 | 24 | 25 | # Contribution Guidelines 26 | Thank you for considering contributing to this project! We appreciate your time and effort in improving our work. Below are the guidelines to help you contribute effectively, 27 | but first, join our [Telegram](https://t.me/+-84e2pqLtqNkZDAx)! 28 | 29 | # How to Contribute 30 | ### 1. Fork the Repository: 31 | Start by forking this repository to your GitHub account. 32 | 33 | ### 2. Clone the Repository: 34 | After forking, clone the repository to your local machine: 35 | ``` bash 36 | git clone https://github.com/your-user/ByteBeastsBackend.git 37 | cd ByteBeastBackend 38 | ``` 39 | 40 | ### 3. Create a New Branch: 41 | Create a new branch for your feature or bug fix following the branch naming convention: 42 | - For bugs: `bug-fix-name` 43 | - For new features: `feat-name` 44 | ``` bash 45 | git checkout -b feature-name 46 | ``` 47 | 48 | ### 4. Make Changes: 49 | Make your changes to the codebase. Ensure your code adheres to the project's coding style and standards. Make sure to add/update tests if needed. 50 | 51 | ### 5. Run Tests: 52 | Before submitting your changes, run the existing test suite to ensure your code does not break anything: 53 | 54 | Start the Katana environment 55 | ``` bash 56 | # Run Katana 57 | katana --disable-fee --allowed-origins "*" 58 | ``` 59 | 60 | ``` bash 61 | # Build the example 62 | sozo build 63 | ``` 64 | 65 | ``` bash 66 | # Run tests 67 | sozo test 68 | ``` 69 | 70 | ``` bash 71 | # Apply migrations 72 | sozo migrate apply 73 | ``` 74 | 75 | ### 6. Commit Your Changes: 76 | Use a descriptive commit message that explains your changes clearly. 77 | 78 | ### 7. Push to Your Fork: 79 | Push your changes to your forked repository. 80 | 81 | 82 | ### 8. Submit a Pull Request: 83 | Once your changes are ready, submit a Pull Request (PR) for review. Ensure that: 84 | 85 | - Your PR has a clear and descriptive title. 86 | - You provide a detailed explanation of the changes made. 87 | - You reference any related issues (if applicable). 88 | 89 | All contributions must go through the PR review process to maintain code quality and consistency. 90 | Once your PR is reviewed, the maintainers will provide feedback or merge it into the main branch. 91 | 92 | Thank you for your contribution, and we look forward to collaborating with you! 93 | -------------------------------------------------------------------------------- /src/models/npc.cairo: -------------------------------------------------------------------------------- 1 | use super::role::Role; 2 | use super::coordinates::Coordinates; 3 | use super::mission_status::MissionStatus; 4 | use super::potion::Potion; 5 | 6 | use array::ArrayTrait; 7 | 8 | #[derive(Drop, Serde)] 9 | #[dojo::model] 10 | pub struct NPC { 11 | #[key] 12 | pub npc_id: u32, // Unique identifier for the NPC 13 | pub npc_name: felt252, // Name of the NPC 14 | pub npc_description: felt252, // Description of the NPC 15 | pub npc_role: Role, // Role of the NPC, defined by the Role enum 16 | pub dialogue: ByteArray, // Default dialogue for the NPC 17 | pub is_active: bool, // Whether the NPC is currently active in the game 18 | pub location: Coordinates, // Fixed location of the NPC on the map 19 | pub importance_level: u8, // Level of importance of the NPC in the game 20 | pub mission_status: MissionStatus, // Status of the mission associated with the NPC 21 | pub reward: u16, // Fixed reward given by the NPC 22 | pub experience_points: u16, // Experience points given by the NPC 23 | pub potions: Array, // Items held by the NPC 24 | } 25 | 26 | 27 | #[cfg(test)] 28 | mod tests { 29 | use bytebeasts::{ 30 | models::{role::Role, coordinates::Coordinates, mission_status::MissionStatus, npc::NPC, potion::Potion}, 31 | }; 32 | use array::ArrayTrait; 33 | 34 | #[test] 35 | fn test_npc_creation() { 36 | let mut npc = NPC { 37 | npc_id: 1, 38 | npc_name: 'Gandalf', 39 | npc_description: 'A wise old wizard', 40 | npc_role: Role::Guide, 41 | dialogue: "Welcome to Middle-earth!", 42 | is_active: true, 43 | location: Coordinates { x: 100, y: 200 }, 44 | importance_level: 5, 45 | mission_status: MissionStatus::NotStarted, 46 | reward: 50, 47 | experience_points: 100, 48 | potions: ArrayTrait::new(), 49 | }; 50 | let potion = Potion { 51 | potion_id: 1, 52 | potion_name: 'Restore everything', 53 | potion_effect: 50, 54 | }; 55 | 56 | npc.potions.append(potion); 57 | 58 | assert_eq!(npc.npc_id, 1); 59 | assert_eq!(npc.npc_name, 'Gandalf'); 60 | assert_eq!(npc.npc_description, 'A wise old wizard'); 61 | assert_eq!(npc.npc_role.into(), 2); // Role::Guide -> 2 62 | assert!(npc.is_active); 63 | assert_eq!(npc.location.x, 100); 64 | assert_eq!(npc.location.y, 200); 65 | assert_eq!(npc.importance_level, 5); 66 | assert_eq!(npc.mission_status.into(), 0); // MissionStatus::NotStarted -> 0 67 | assert_eq!(npc.reward, 50); 68 | assert_eq!(npc.experience_points, 100); 69 | assert_eq!(npc.potions.len(), 1, "NPC should have 1 potion"); 70 | assert_eq!(npc.potions.pop_front().unwrap().potion_id, 1, "NPC potion ID should be 1"); 71 | } 72 | 73 | #[test] 74 | fn test_npc_role_conversion() { 75 | let role_guide: felt252 = Role::Guide.into(); 76 | assert_eq!(role_guide, 2); 77 | 78 | let role_vendor: felt252 = Role::Vendor.into(); 79 | assert_eq!(role_vendor, 0); 80 | } 81 | 82 | #[test] 83 | fn test_mission_status_conversion() { 84 | let status_in_progress: felt252 = MissionStatus::InProgress.into(); 85 | assert_eq!(status_in_progress, 1); 86 | 87 | let status_completed: felt252 = MissionStatus::Completed.into(); 88 | assert_eq!(status_completed, 2); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/models/game.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | use super::game_player::GamePlayer; 3 | 4 | #[derive(Serde, Copy, Drop, Introspect, PartialEq)] 5 | pub enum GameStatus { 6 | Pending: (), 7 | InProgress: (), 8 | Finished: (), 9 | } 10 | 11 | #[derive(Copy, Drop, Serde)] 12 | #[dojo::model] 13 | pub struct Game { 14 | #[key] 15 | pub game_id: u128, 16 | pub player_1: ContractAddress, 17 | pub player_2: ContractAddress, 18 | pub player_3: ContractAddress, 19 | pub player_4: ContractAddress, 20 | pub status: GameStatus, 21 | pub is_private: bool, 22 | } 23 | 24 | pub trait GameTrait { 25 | fn new(game_id: u128, player_1: ContractAddress) -> Game; 26 | fn join_game(ref self: Game, player_2: GamePlayer); 27 | } 28 | 29 | pub impl GameImpl of GameTrait { 30 | // create the game 31 | fn new(game_id: u128, player_1: ContractAddress) -> Game { 32 | let game: Game = Game { 33 | game_id: game_id, 34 | player_1: player_1, 35 | player_2: core::num::traits::Zero::::zero(), 36 | player_3: core::num::traits::Zero::::zero(), 37 | player_4: core::num::traits::Zero::::zero(), 38 | status: GameStatus::InProgress, 39 | is_private: false, 40 | }; 41 | game 42 | } 43 | 44 | // player two can join the game 45 | fn join_game(ref self: Game, player_2: GamePlayer) { 46 | self.player_2 = player_2.address; 47 | } 48 | } 49 | 50 | #[cfg(test)] 51 | mod tests { 52 | use bytebeasts::{models::{game_player::GamePlayer, game::GameStatus, game::GameTrait}}; 53 | use starknet::{ContractAddress, get_caller_address, SyscallResultTrait}; 54 | 55 | #[test] 56 | fn test_game_creation() { 57 | // Crear una dirección de contrato de prueba 58 | let player_1_address = get_caller_address(); 59 | let game_id = 98765432101234567890123456789012_u128; 60 | 61 | // Crear el juego usando el método `new` 62 | let game = GameTrait::new(game_id, player_1_address); 63 | 64 | // Verificar que los campos se inicializan correctamente 65 | assert_eq!(game.game_id, game_id, "El game_id deberia ser el esperado"); 66 | assert_eq!(game.player_1, player_1_address, "El player_1 deberia ser la direccion del jugador 1"); 67 | assert_eq!(game.is_private, false, "El juego deberia ser publico por defecto"); 68 | } 69 | 70 | #[test] 71 | fn test_player_2_joins_game() { 72 | // Crear direcciones de contrato de prueba 73 | let player_1_address = get_caller_address(); 74 | let player_2_address = get_caller_address(); 75 | let game_id = 98765432101234567890123456789012_u128; 76 | 77 | // Crear un juego con el jugador 1 78 | let mut game = GameTrait::new(game_id, player_1_address); 79 | 80 | // Crear un jugador 2 con la dirección de contrato de prueba 81 | let player_2 = GamePlayer { 82 | address: player_2_address, 83 | game_id, 84 | beast_1: 0, 85 | beast_2: 0, 86 | beast_3: 0, 87 | beast_4: 0, 88 | bag_id: 0, 89 | active_mount: 0, 90 | mounts: ArrayTrait::new(), 91 | position: ArrayTrait::new(), 92 | }; 93 | 94 | // Hacer que el jugador 2 se una al juego 95 | game.join_game(player_2); 96 | 97 | // Verificar que player_2 se haya unido al juego correctamente 98 | assert_eq!(game.player_2, player_2_address, "El player_2 deberia ser la direccion del jugador 2"); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/systems/tournament.cairo: -------------------------------------------------------------------------------- 1 | use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; 2 | use bytebeasts::{models::{tournament::Tournament, tournament::TournamentStatus},}; 3 | 4 | #[dojo::interface] 5 | trait ITournamentAction { 6 | fn create_tournament( 7 | ref world: IWorldDispatcher, 8 | tournament_id: u32, 9 | name: felt252, 10 | status: TournamentStatus, 11 | entry_fee: u32, 12 | max_participants: u32, 13 | current_participants: Array, 14 | prize_pool: u32 15 | ); 16 | fn register_player(ref world: IWorldDispatcher, tournament_id: u32, new_player_id: u32); 17 | fn start_tournament(ref world: IWorldDispatcher, tournament_id: u32); 18 | fn complete_tournament(ref world: IWorldDispatcher, tournament_id: u32, player_id: u32); 19 | fn get_tournament(world: @IWorldDispatcher, tournament_id: u32) -> Tournament; 20 | } 21 | 22 | 23 | #[dojo::contract] 24 | mod tournament_system { 25 | use super::ITournamentAction; 26 | use bytebeasts::{ 27 | models::{tournament::Tournament, tournament::TournamentStatus}, 28 | }; 29 | 30 | #[abi(embed_v0)] 31 | impl TournamentActionImpl of ITournamentAction { 32 | fn create_tournament( 33 | ref world: IWorldDispatcher, 34 | tournament_id: u32, 35 | name: felt252, 36 | status: TournamentStatus, 37 | entry_fee: u32, 38 | max_participants: u32, 39 | current_participants: Array, 40 | prize_pool: u32 41 | ) { 42 | let tournament = Tournament { 43 | tournament_id: tournament_id, 44 | name: name, 45 | status: status, 46 | entry_fee: entry_fee, 47 | max_participants: max_participants, 48 | current_participants: current_participants, 49 | prize_pool: prize_pool 50 | }; 51 | set!(world, (tournament)) 52 | } 53 | 54 | fn register_player(ref world: IWorldDispatcher, tournament_id: u32, new_player_id: u32) { 55 | let mut tournament = get!(world, tournament_id, (Tournament)); 56 | 57 | assert!(tournament.status == TournamentStatus::Pending, "Tournament not open for registration"); 58 | 59 | assert!( 60 | tournament.current_participants.len() < tournament.max_participants.try_into().unwrap(), 61 | "Tournament is full" 62 | ); 63 | 64 | tournament.current_participants.append(new_player_id); 65 | 66 | set!(world, (tournament)); 67 | } 68 | 69 | fn start_tournament(ref world: IWorldDispatcher, tournament_id: u32) { 70 | let mut tournament = get!(world, tournament_id, (Tournament)); 71 | 72 | assert!(tournament.status == TournamentStatus::Pending, "Tournament not pending"); 73 | 74 | assert!( 75 | tournament.current_participants.len() >= 2, 76 | "Not enough participants to start" 77 | ); 78 | 79 | tournament.status = TournamentStatus::Ongoing; 80 | 81 | set!(world, (tournament)); 82 | } 83 | 84 | fn complete_tournament(ref world: IWorldDispatcher, tournament_id: u32, player_id: u32) { 85 | let tournament = get!(world, tournament_id, (Tournament)); 86 | 87 | assert!(tournament.status == TournamentStatus::Ongoing, "Tournament not ongoing"); 88 | 89 | // Validate winner is a participant 90 | let mut is_participant = false; 91 | for participant in tournament.current_participants { 92 | if participant == player_id { 93 | is_participant = true; 94 | break; 95 | } 96 | }; 97 | assert!(is_participant, "Winner not participant"); 98 | 99 | // TODO distribute prize pool to winner 100 | let mut tournament = get!(world, tournament_id, (Tournament)); 101 | tournament.status = TournamentStatus::Completed; 102 | 103 | set!(world, (tournament)); 104 | } 105 | 106 | fn get_tournament(world: @IWorldDispatcher, tournament_id: u32) -> Tournament { 107 | let tournament_from_world = get!(world, tournament_id, (Tournament)); 108 | tournament_from_world 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/models/erc721/interface.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | 3 | const IERC721_ID: felt252 = 0x33eb2f84c309543403fd69f0d0f363781ef06ef6faeb0131ff16ea3175bd943; 4 | const IERC721_METADATA_ID: felt252 = 5 | 0x6069a70848f907fa57668ba1875164eb4dcee693952468581406d131081bbd; 6 | const IERC721_RECEIVER_ID: felt252 = 7 | 0x3a0dff5f70d80458ad14ae37bb182a728e3c8cdda0402a5daa86620bdf910bc; 8 | 9 | #[starknet::interface] 10 | trait IERC721 { 11 | fn balance_of(self: @TState, account: ContractAddress) -> u256; 12 | fn owner_of(self: @TState, token_id: u256) -> ContractAddress; 13 | fn safe_transfer_from( 14 | ref self: TState, 15 | from: ContractAddress, 16 | to: ContractAddress, 17 | token_id: u256, 18 | data: Span 19 | ); 20 | fn transfer_from(ref self: TState, from: ContractAddress, to: ContractAddress, token_id: u256); 21 | fn approve(ref self: TState, to: ContractAddress, token_id: u256); 22 | fn set_approval_for_all(ref self: TState, operator: ContractAddress, approved: bool); 23 | fn get_approved(self: @TState, token_id: u256) -> ContractAddress; 24 | fn is_approved_for_all( 25 | self: @TState, owner: ContractAddress, operator: ContractAddress 26 | ) -> bool; 27 | } 28 | 29 | #[starknet::interface] 30 | trait IERC721Metadata { 31 | fn name(self: @TState) -> felt252; 32 | fn symbol(self: @TState) -> felt252; 33 | fn token_uri(self: @TState, token_id: u256) -> felt252; 34 | } 35 | 36 | #[starknet::interface] 37 | trait IERC721CamelOnly { 38 | fn balanceOf(self: @TState, account: ContractAddress) -> u256; 39 | fn ownerOf(self: @TState, tokenId: u256) -> ContractAddress; 40 | fn safeTransferFrom( 41 | ref self: TState, 42 | from: ContractAddress, 43 | to: ContractAddress, 44 | tokenId: u256, 45 | data: Span 46 | ); 47 | fn transferFrom(ref self: TState, from: ContractAddress, to: ContractAddress, tokenId: u256); 48 | fn setApprovalForAll(ref self: TState, operator: ContractAddress, approved: bool); 49 | fn getApproved(self: @TState, tokenId: u256) -> ContractAddress; 50 | fn isApprovedForAll(self: @TState, owner: ContractAddress, operator: ContractAddress) -> bool; 51 | } 52 | 53 | #[starknet::interface] 54 | trait IERC721MetadataCamelOnly { 55 | fn tokenURI(self: @TState, tokenId: u256) -> felt252; 56 | } 57 | 58 | // 59 | // ERC721 ABI 60 | // 61 | 62 | #[starknet::interface] 63 | trait ERC721ABI { 64 | // IERC721 65 | fn balance_of(self: @TState, account: ContractAddress) -> u256; 66 | fn owner_of(self: @TState, token_id: u256) -> ContractAddress; 67 | fn safe_transfer_from( 68 | ref self: TState, 69 | from: ContractAddress, 70 | to: ContractAddress, 71 | token_id: u256, 72 | data: Span 73 | ); 74 | fn transfer_from(ref self: TState, from: ContractAddress, to: ContractAddress, token_id: u256); 75 | fn approve(ref self: TState, to: ContractAddress, token_id: u256); 76 | fn set_approval_for_all(ref self: TState, operator: ContractAddress, approved: bool); 77 | fn get_approved(self: @TState, token_id: u256) -> ContractAddress; 78 | fn is_approved_for_all( 79 | self: @TState, owner: ContractAddress, operator: ContractAddress 80 | ) -> bool; 81 | 82 | // IERC721Metadata 83 | fn name(self: @TState) -> felt252; 84 | fn symbol(self: @TState) -> felt252; 85 | fn token_uri(self: @TState, token_id: u256) -> felt252; 86 | 87 | // IERC721CamelOnly 88 | fn balanceOf(self: @TState, account: ContractAddress) -> u256; 89 | fn ownerOf(self: @TState, tokenId: u256) -> ContractAddress; 90 | fn safeTransferFrom( 91 | ref self: TState, 92 | from: ContractAddress, 93 | to: ContractAddress, 94 | tokenId: u256, 95 | data: Span 96 | ); 97 | fn transferFrom(ref self: TState, from: ContractAddress, to: ContractAddress, tokenId: u256); 98 | fn setApprovalForAll(ref self: TState, operator: ContractAddress, approved: bool); 99 | fn getApproved(self: @TState, tokenId: u256) -> ContractAddress; 100 | fn isApprovedForAll(self: @TState, owner: ContractAddress, operator: ContractAddress) -> bool; 101 | 102 | // IERC721MetadataCamelOnly 103 | fn tokenURI(self: @TState, tokenId: u256) -> felt252; 104 | } 105 | 106 | // 107 | // ERC721Receiver 108 | // 109 | 110 | #[starknet::interface] 111 | trait IERC721Receiver { 112 | fn on_erc721_received( 113 | self: @TState, 114 | operator: ContractAddress, 115 | from: ContractAddress, 116 | token_id: u256, 117 | data: Span 118 | ) -> felt252; 119 | } 120 | 121 | #[starknet::interface] 122 | trait IERC721ReceiverCamel { 123 | fn onERC721Received( 124 | self: @TState, 125 | operator: ContractAddress, 126 | from: ContractAddress, 127 | tokenId: u256, 128 | data: Span 129 | ) -> felt252; 130 | } 131 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ByteBeats official logo 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | [![Telegram Chat][tg-badge]][tg-url] 15 | 16 | [tg-badge]: https://img.shields.io/endpoint?color=neon&logo=telegram&label=chat&style=flat-square&url=https%3A%2F%2Ftg.sumanjay.workers.dev%2Fdojoengine 17 | [tg-url]: https://t.me/+-84e2pqLtqNkZDAx 18 | 19 | ## Maintainers 🥷 20 | 21 | 22 | 23 | 29 | 35 | 36 |
24 | Maintainer: danielcdz 25 |
26 | danielcdz 27 |
28 |
30 | Maintainer: Marco 31 |
32 | Marco 33 |
34 |
37 | 38 | # Byte Beasts: Official Guide 🐉🎮 39 | 40 | The official Byte Beasts guide, the quickest and most streamlined way to get your Dojo provable game up and running. This guide will assist you with the initial setup, from cloning the repository to deploying your world. 41 | 42 | Read the full tutorial [here](https://book.dojoengine.org/tutorial/dojo-starter). 43 | 44 | ## Prerequisites 📋 45 | 46 | To be able to run the ByteBeasts backend you need to have Git, Rust and Scarb installed on your PC to satisfy Dojo dependencies. You can install them with the following steps: 47 | 48 | ### Install Rust 🦀 49 | 50 | Go to the [Rust installation page](https://doc.rust-lang.org/book/ch01-01-installation.html#installing-rustup-on-linux-or-macos) 51 | 52 | After installing Rust, ensure your `PATH` environment variable includes the Cargo bin directory (usually `$HOME/.cargo/bin`). 53 | 54 | ### Install Git 🧑‍💻 55 | 56 | Go to the [Git installation page](https://git-scm.com/downloads) and follow the instructions for your operating system to install Git. 57 | 58 | ### Install Scarb ⚙️ 59 | 60 | The Dojo toolchain integrates [Scarb](https://docs.swmansion.com/scarb/) to build and run Dojo projects, installation instructions are [here](https://docs.swmansion.com/scarb/download.html). 61 | 62 | ### Install Dojo using `dojoup` 🥋 63 | 64 | You can install with the `dojoup` version manager which enables you to easily install, update and manage your Dojo installation. 65 | 66 | ### Install dojoup 🛠️ 67 | 68 | ```bash 69 | curl -L https://install.dojoengine.org | bash 70 | ``` 71 | 72 | ### Install the Dojo v1.0.0-alpha.5 release 🚀 73 | 74 | dojoup --version 1.0.0-alpha.5 75 | 76 | ### Install Dojo using `asdf` 📦 77 | 78 | You can alternatively use the `asdf` package manager to install and manage your Dojo installation. 79 | 80 | ### Install asdf 81 | 82 | Follow the [asdf installation instructions](https://asdf-vm.com/guide/getting-started.html) 83 | 84 | ### Add the asdf-dojo plugin 🔌 85 | 86 | ```bash 87 | asdf plugin add dojo https://github.com/dojoengine/asdf-dojo 88 | ``` 89 | 90 | ### Install the latest or a specific version 🆕 91 | 92 | ```bash 93 | asdf install dojo latest # For the latest version 94 | asdf install dojo 0.7.0 # For a specific version 95 | 96 | ``` 97 | 98 | ### Set the global or local version 📁 99 | 100 | ```bash 101 | asdf global dojo latest # Set globally 102 | asdf local dojo 0.7.0 # Set locally in your project directory 103 | 104 | ``` 105 | 106 | ### Setup the hooks 107 | 108 | This project uses `Git hooks` to ensure code quality and prevent issues before they reach the remote repository. 109 | 110 | #### Pre-push Hook 111 | 112 | We have implemented a `pre-push` hook that automatically runs tests before any code is pushed to the remote repository. This helps maintain code quality and prevents broken code from being pushed. 113 | 114 | ##### What it does 115 | 116 | - Runs `sozo test` automatically before each push 117 | - Blocks the push if tests fail 118 | - Allows the push to proceed only if all tests pass 119 | 120 | ##### Setup Instructions 121 | 122 | ```bash 123 | # Run Katana 124 | make init 125 | ``` 126 | 127 | ## Running Locally 🖥️ 128 | 129 | ### Terminal one (Make sure this is running) 🏃 130 | 131 | ```bash 132 | # Run Katana 133 | make katana 134 | ``` 135 | 136 | ### Terminal two 🔄 137 | 138 | ```bash 139 | # Build migrate and start torii 140 | make setup 141 | ``` 142 | 143 | ## Contribution 🤝 144 | We welcome contributions from developers of all levels! If you're interested in contributing to this project, please follow our [CONTRIBUTION GUIDELINES](./docs/contribution/CONTRIBUTION.md) to get started. 145 | 146 | Whether it's fixing bugs, improving documentation, or adding new features, your help is greatly appreciated. Don't hesitate to ask questions or reach out for support—we're here to help! 147 | 148 | ## Communication channel 📢 149 | 150 | If you're a contributor or would like to connect with the project maintainers, feel free to join our [Telegram](https://t.me/+-84e2pqLtqNkZDAx) group! 151 | -------------------------------------------------------------------------------- /src/models/evolution.cairo: -------------------------------------------------------------------------------- 1 | use core::result::Result; 2 | 3 | #[derive(Drop, Copy, Serde)] 4 | #[dojo::model] 5 | struct Evolution { 6 | #[key] 7 | pub base_beast_id: u32, 8 | pub evolved_beast_id: u32, 9 | pub level_requirement: u32, 10 | pub required_battles: u32, 11 | pub required_item: Option 12 | } 13 | 14 | mod rules { 15 | /// Minimum level required before evolution is possible 16 | const LEVEL_REQUIREMENT: u32 = 10; 17 | /// Minimum number of battles required before evolution 18 | const REQUIRED_BATTLES: u32 = 5; 19 | /// Item ID required for evolution (special evolution stone) 20 | const REQUIRED_ITEM: u32 = 1001; 21 | } 22 | 23 | #[generate_trait] 24 | impl EvolutionImpl of EvolutionTrait { 25 | fn can_evolve(self: Evolution) -> bool { 26 | let is_valid_item: bool = match self.required_item { 27 | Option::Some(val) => val == rules::REQUIRED_ITEM, 28 | Option::None => true, 29 | }; 30 | 31 | is_valid_item && 32 | self.level_requirement > rules::LEVEL_REQUIREMENT && 33 | self.required_battles > rules::REQUIRED_BATTLES 34 | } 35 | 36 | fn evolve(ref self: Evolution) -> Result { 37 | assert(self.base_beast_id != 0, 'Invalid base beast'); 38 | 39 | match self.can_evolve() { 40 | true => { 41 | // TODO: investigate how can we make It random 42 | self.evolved_beast_id = self.base_beast_id * 10_u32; 43 | Result::Ok(self.evolved_beast_id) 44 | }, 45 | false => Result::Err('Evolution requirements not met'), 46 | } 47 | } 48 | } 49 | 50 | 51 | #[cfg(test)] 52 | mod tests { 53 | use super::{Evolution, EvolutionTrait}; 54 | use core::result::Result; 55 | 56 | #[test] 57 | fn test_evolution_with_valid_requirements() { 58 | 59 | let mut evolution = Evolution { 60 | base_beast_id: 1_u32, 61 | evolved_beast_id: 0_u32, 62 | level_requirement: 15_u32, 63 | required_battles: 10_u32, 64 | required_item: Option::Some(1001_u32) 65 | }; 66 | 67 | let result = evolution.evolve(); 68 | 69 | match result { 70 | Result::Ok(evolved_id) => { 71 | assert(evolved_id == 10_u32, 'Incorrect evolution ID'); 72 | assert(evolution.evolved_beast_id == 10_u32, 'Beast not evolved correctly'); 73 | }, 74 | Result::Err(_) => { 75 | panic!("Evolution should have succeeded") 76 | } 77 | } 78 | } 79 | 80 | #[test] 81 | fn test_evolution_with_invalid_level() { 82 | 83 | let mut evolution = Evolution { 84 | base_beast_id: 1_u32, 85 | evolved_beast_id: 0_u32, 86 | level_requirement: 5_u32, 87 | required_battles: 10_u32, 88 | required_item: Option::Some(1001_u32) 89 | }; 90 | 91 | let result = evolution.evolve(); 92 | 93 | match result { 94 | Result::Ok(_) => { 95 | panic!("Evolution should have failed due to low level") 96 | }, 97 | Result::Err(e) => { 98 | assert(e == 'Evolution requirements not met', 'Unexpected error message'); 99 | } 100 | } 101 | } 102 | 103 | #[test] 104 | fn test_evolution_with_invalid_battles() { 105 | 106 | let mut evolution = Evolution { 107 | base_beast_id: 1_u32, 108 | evolved_beast_id: 0_u32, 109 | level_requirement: 15_u32, 110 | required_battles: 3_u32, 111 | required_item: Option::Some(1001_u32) 112 | }; 113 | 114 | let result = evolution.evolve(); 115 | match result { 116 | Result::Ok(_) => { 117 | panic!("Evolution should have failed due to insufficient battles") 118 | }, 119 | Result::Err(e) => { 120 | assert(e == 'Evolution requirements not met', 'Unexpected error message'); 121 | } 122 | } 123 | } 124 | 125 | #[test] 126 | fn test_evolution_with_invalid_item() { 127 | 128 | let mut evolution = Evolution { 129 | base_beast_id: 1_u32, 130 | evolved_beast_id: 0_u32, 131 | level_requirement: 15_u32, 132 | required_battles: 10_u32, 133 | required_item: Option::Some(999_u32) 134 | }; 135 | 136 | let result = evolution.evolve(); 137 | match result { 138 | Result::Ok(_) => { 139 | panic!("Evolution should have failed due to wrong item") 140 | }, 141 | Result::Err(e) => { 142 | assert(e == 'Evolution requirements not met', 'Unexpected error message'); 143 | } 144 | } 145 | } 146 | 147 | #[test] 148 | fn test_evolution_with_no_item_requirement() { 149 | 150 | let mut evolution = Evolution { 151 | base_beast_id: 1_u32, 152 | evolved_beast_id: 0_u32, 153 | level_requirement: 15_u32, 154 | required_battles: 10_u32, 155 | required_item: Option::None 156 | }; 157 | 158 | let result = evolution.evolve(); 159 | 160 | match result { 161 | Result::Ok(evolved_id) => { 162 | assert(evolved_id == 10_u32, 'Incorrect evolution ID'); 163 | }, 164 | Result::Err(_) => { 165 | panic!("Evolution should have succeeded without item requirement") 166 | } 167 | } 168 | } 169 | } -------------------------------------------------------------------------------- /manifests/dev/base/abis/contracts/bytebeasts-world_setup-674b640b.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "impl", 4 | "name": "ContractImpl", 5 | "interface_name": "dojo::contract::contract::IContract" 6 | }, 7 | { 8 | "type": "struct", 9 | "name": "core::byte_array::ByteArray", 10 | "members": [ 11 | { 12 | "name": "data", 13 | "type": "core::array::Array::" 14 | }, 15 | { 16 | "name": "pending_word", 17 | "type": "core::felt252" 18 | }, 19 | { 20 | "name": "pending_word_len", 21 | "type": "core::integer::u32" 22 | } 23 | ] 24 | }, 25 | { 26 | "type": "interface", 27 | "name": "dojo::contract::contract::IContract", 28 | "items": [ 29 | { 30 | "type": "function", 31 | "name": "contract_name", 32 | "inputs": [], 33 | "outputs": [ 34 | { 35 | "type": "core::byte_array::ByteArray" 36 | } 37 | ], 38 | "state_mutability": "view" 39 | }, 40 | { 41 | "type": "function", 42 | "name": "namespace", 43 | "inputs": [], 44 | "outputs": [ 45 | { 46 | "type": "core::byte_array::ByteArray" 47 | } 48 | ], 49 | "state_mutability": "view" 50 | }, 51 | { 52 | "type": "function", 53 | "name": "tag", 54 | "inputs": [], 55 | "outputs": [ 56 | { 57 | "type": "core::byte_array::ByteArray" 58 | } 59 | ], 60 | "state_mutability": "view" 61 | }, 62 | { 63 | "type": "function", 64 | "name": "name_hash", 65 | "inputs": [], 66 | "outputs": [ 67 | { 68 | "type": "core::felt252" 69 | } 70 | ], 71 | "state_mutability": "view" 72 | }, 73 | { 74 | "type": "function", 75 | "name": "namespace_hash", 76 | "inputs": [], 77 | "outputs": [ 78 | { 79 | "type": "core::felt252" 80 | } 81 | ], 82 | "state_mutability": "view" 83 | }, 84 | { 85 | "type": "function", 86 | "name": "selector", 87 | "inputs": [], 88 | "outputs": [ 89 | { 90 | "type": "core::felt252" 91 | } 92 | ], 93 | "state_mutability": "view" 94 | } 95 | ] 96 | }, 97 | { 98 | "type": "impl", 99 | "name": "WorldProviderImpl", 100 | "interface_name": "dojo::world::world_contract::IWorldProvider" 101 | }, 102 | { 103 | "type": "struct", 104 | "name": "dojo::world::world_contract::IWorldDispatcher", 105 | "members": [ 106 | { 107 | "name": "contract_address", 108 | "type": "core::starknet::contract_address::ContractAddress" 109 | } 110 | ] 111 | }, 112 | { 113 | "type": "interface", 114 | "name": "dojo::world::world_contract::IWorldProvider", 115 | "items": [ 116 | { 117 | "type": "function", 118 | "name": "world", 119 | "inputs": [], 120 | "outputs": [ 121 | { 122 | "type": "dojo::world::world_contract::IWorldDispatcher" 123 | } 124 | ], 125 | "state_mutability": "view" 126 | } 127 | ] 128 | }, 129 | { 130 | "type": "impl", 131 | "name": "WorldSetupImpl", 132 | "interface_name": "bytebeasts::systems::world_setup::IWorldSetup" 133 | }, 134 | { 135 | "type": "interface", 136 | "name": "bytebeasts::systems::world_setup::IWorldSetup", 137 | "items": [ 138 | { 139 | "type": "function", 140 | "name": "setWorld", 141 | "inputs": [], 142 | "outputs": [], 143 | "state_mutability": "external" 144 | } 145 | ] 146 | }, 147 | { 148 | "type": "impl", 149 | "name": "IDojoInitImpl", 150 | "interface_name": "bytebeasts::systems::world_setup::world_setup::IDojoInit" 151 | }, 152 | { 153 | "type": "interface", 154 | "name": "bytebeasts::systems::world_setup::world_setup::IDojoInit", 155 | "items": [ 156 | { 157 | "type": "function", 158 | "name": "dojo_init", 159 | "inputs": [], 160 | "outputs": [], 161 | "state_mutability": "view" 162 | } 163 | ] 164 | }, 165 | { 166 | "type": "impl", 167 | "name": "UpgradableImpl", 168 | "interface_name": "dojo::contract::upgradeable::IUpgradeable" 169 | }, 170 | { 171 | "type": "interface", 172 | "name": "dojo::contract::upgradeable::IUpgradeable", 173 | "items": [ 174 | { 175 | "type": "function", 176 | "name": "upgrade", 177 | "inputs": [ 178 | { 179 | "name": "new_class_hash", 180 | "type": "core::starknet::class_hash::ClassHash" 181 | } 182 | ], 183 | "outputs": [], 184 | "state_mutability": "external" 185 | } 186 | ] 187 | }, 188 | { 189 | "type": "event", 190 | "name": "dojo::contract::upgradeable::upgradeable::Upgraded", 191 | "kind": "struct", 192 | "members": [ 193 | { 194 | "name": "class_hash", 195 | "type": "core::starknet::class_hash::ClassHash", 196 | "kind": "data" 197 | } 198 | ] 199 | }, 200 | { 201 | "type": "event", 202 | "name": "dojo::contract::upgradeable::upgradeable::Event", 203 | "kind": "enum", 204 | "variants": [ 205 | { 206 | "name": "Upgraded", 207 | "type": "dojo::contract::upgradeable::upgradeable::Upgraded", 208 | "kind": "nested" 209 | } 210 | ] 211 | }, 212 | { 213 | "type": "event", 214 | "name": "bytebeasts::systems::world_setup::world_setup::Event", 215 | "kind": "enum", 216 | "variants": [ 217 | { 218 | "name": "UpgradeableEvent", 219 | "type": "dojo::contract::upgradeable::upgradeable::Event", 220 | "kind": "nested" 221 | } 222 | ] 223 | } 224 | ] -------------------------------------------------------------------------------- /manifests/dev/deployment/abis/contracts/bytebeasts-world_setup-674b640b.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "impl", 4 | "name": "ContractImpl", 5 | "interface_name": "dojo::contract::contract::IContract" 6 | }, 7 | { 8 | "type": "struct", 9 | "name": "core::byte_array::ByteArray", 10 | "members": [ 11 | { 12 | "name": "data", 13 | "type": "core::array::Array::" 14 | }, 15 | { 16 | "name": "pending_word", 17 | "type": "core::felt252" 18 | }, 19 | { 20 | "name": "pending_word_len", 21 | "type": "core::integer::u32" 22 | } 23 | ] 24 | }, 25 | { 26 | "type": "interface", 27 | "name": "dojo::contract::contract::IContract", 28 | "items": [ 29 | { 30 | "type": "function", 31 | "name": "contract_name", 32 | "inputs": [], 33 | "outputs": [ 34 | { 35 | "type": "core::byte_array::ByteArray" 36 | } 37 | ], 38 | "state_mutability": "view" 39 | }, 40 | { 41 | "type": "function", 42 | "name": "namespace", 43 | "inputs": [], 44 | "outputs": [ 45 | { 46 | "type": "core::byte_array::ByteArray" 47 | } 48 | ], 49 | "state_mutability": "view" 50 | }, 51 | { 52 | "type": "function", 53 | "name": "tag", 54 | "inputs": [], 55 | "outputs": [ 56 | { 57 | "type": "core::byte_array::ByteArray" 58 | } 59 | ], 60 | "state_mutability": "view" 61 | }, 62 | { 63 | "type": "function", 64 | "name": "name_hash", 65 | "inputs": [], 66 | "outputs": [ 67 | { 68 | "type": "core::felt252" 69 | } 70 | ], 71 | "state_mutability": "view" 72 | }, 73 | { 74 | "type": "function", 75 | "name": "namespace_hash", 76 | "inputs": [], 77 | "outputs": [ 78 | { 79 | "type": "core::felt252" 80 | } 81 | ], 82 | "state_mutability": "view" 83 | }, 84 | { 85 | "type": "function", 86 | "name": "selector", 87 | "inputs": [], 88 | "outputs": [ 89 | { 90 | "type": "core::felt252" 91 | } 92 | ], 93 | "state_mutability": "view" 94 | } 95 | ] 96 | }, 97 | { 98 | "type": "impl", 99 | "name": "WorldProviderImpl", 100 | "interface_name": "dojo::world::world_contract::IWorldProvider" 101 | }, 102 | { 103 | "type": "struct", 104 | "name": "dojo::world::world_contract::IWorldDispatcher", 105 | "members": [ 106 | { 107 | "name": "contract_address", 108 | "type": "core::starknet::contract_address::ContractAddress" 109 | } 110 | ] 111 | }, 112 | { 113 | "type": "interface", 114 | "name": "dojo::world::world_contract::IWorldProvider", 115 | "items": [ 116 | { 117 | "type": "function", 118 | "name": "world", 119 | "inputs": [], 120 | "outputs": [ 121 | { 122 | "type": "dojo::world::world_contract::IWorldDispatcher" 123 | } 124 | ], 125 | "state_mutability": "view" 126 | } 127 | ] 128 | }, 129 | { 130 | "type": "impl", 131 | "name": "WorldSetupImpl", 132 | "interface_name": "bytebeasts::systems::world_setup::IWorldSetup" 133 | }, 134 | { 135 | "type": "interface", 136 | "name": "bytebeasts::systems::world_setup::IWorldSetup", 137 | "items": [ 138 | { 139 | "type": "function", 140 | "name": "setWorld", 141 | "inputs": [], 142 | "outputs": [], 143 | "state_mutability": "external" 144 | } 145 | ] 146 | }, 147 | { 148 | "type": "impl", 149 | "name": "IDojoInitImpl", 150 | "interface_name": "bytebeasts::systems::world_setup::world_setup::IDojoInit" 151 | }, 152 | { 153 | "type": "interface", 154 | "name": "bytebeasts::systems::world_setup::world_setup::IDojoInit", 155 | "items": [ 156 | { 157 | "type": "function", 158 | "name": "dojo_init", 159 | "inputs": [], 160 | "outputs": [], 161 | "state_mutability": "view" 162 | } 163 | ] 164 | }, 165 | { 166 | "type": "impl", 167 | "name": "UpgradableImpl", 168 | "interface_name": "dojo::contract::upgradeable::IUpgradeable" 169 | }, 170 | { 171 | "type": "interface", 172 | "name": "dojo::contract::upgradeable::IUpgradeable", 173 | "items": [ 174 | { 175 | "type": "function", 176 | "name": "upgrade", 177 | "inputs": [ 178 | { 179 | "name": "new_class_hash", 180 | "type": "core::starknet::class_hash::ClassHash" 181 | } 182 | ], 183 | "outputs": [], 184 | "state_mutability": "external" 185 | } 186 | ] 187 | }, 188 | { 189 | "type": "event", 190 | "name": "dojo::contract::upgradeable::upgradeable::Upgraded", 191 | "kind": "struct", 192 | "members": [ 193 | { 194 | "name": "class_hash", 195 | "type": "core::starknet::class_hash::ClassHash", 196 | "kind": "data" 197 | } 198 | ] 199 | }, 200 | { 201 | "type": "event", 202 | "name": "dojo::contract::upgradeable::upgradeable::Event", 203 | "kind": "enum", 204 | "variants": [ 205 | { 206 | "name": "Upgraded", 207 | "type": "dojo::contract::upgradeable::upgradeable::Upgraded", 208 | "kind": "nested" 209 | } 210 | ] 211 | }, 212 | { 213 | "type": "event", 214 | "name": "bytebeasts::systems::world_setup::world_setup::Event", 215 | "kind": "enum", 216 | "variants": [ 217 | { 218 | "name": "UpgradeableEvent", 219 | "type": "dojo::contract::upgradeable::upgradeable::Event", 220 | "kind": "nested" 221 | } 222 | ] 223 | } 224 | ] -------------------------------------------------------------------------------- /manifests/dev/base/abis/contracts/bytebeasts-spawn_action-5176c1e8.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "impl", 4 | "name": "ContractImpl", 5 | "interface_name": "dojo::contract::contract::IContract" 6 | }, 7 | { 8 | "type": "struct", 9 | "name": "core::byte_array::ByteArray", 10 | "members": [ 11 | { 12 | "name": "data", 13 | "type": "core::array::Array::" 14 | }, 15 | { 16 | "name": "pending_word", 17 | "type": "core::felt252" 18 | }, 19 | { 20 | "name": "pending_word_len", 21 | "type": "core::integer::u32" 22 | } 23 | ] 24 | }, 25 | { 26 | "type": "interface", 27 | "name": "dojo::contract::contract::IContract", 28 | "items": [ 29 | { 30 | "type": "function", 31 | "name": "contract_name", 32 | "inputs": [], 33 | "outputs": [ 34 | { 35 | "type": "core::byte_array::ByteArray" 36 | } 37 | ], 38 | "state_mutability": "view" 39 | }, 40 | { 41 | "type": "function", 42 | "name": "namespace", 43 | "inputs": [], 44 | "outputs": [ 45 | { 46 | "type": "core::byte_array::ByteArray" 47 | } 48 | ], 49 | "state_mutability": "view" 50 | }, 51 | { 52 | "type": "function", 53 | "name": "tag", 54 | "inputs": [], 55 | "outputs": [ 56 | { 57 | "type": "core::byte_array::ByteArray" 58 | } 59 | ], 60 | "state_mutability": "view" 61 | }, 62 | { 63 | "type": "function", 64 | "name": "name_hash", 65 | "inputs": [], 66 | "outputs": [ 67 | { 68 | "type": "core::felt252" 69 | } 70 | ], 71 | "state_mutability": "view" 72 | }, 73 | { 74 | "type": "function", 75 | "name": "namespace_hash", 76 | "inputs": [], 77 | "outputs": [ 78 | { 79 | "type": "core::felt252" 80 | } 81 | ], 82 | "state_mutability": "view" 83 | }, 84 | { 85 | "type": "function", 86 | "name": "selector", 87 | "inputs": [], 88 | "outputs": [ 89 | { 90 | "type": "core::felt252" 91 | } 92 | ], 93 | "state_mutability": "view" 94 | } 95 | ] 96 | }, 97 | { 98 | "type": "impl", 99 | "name": "WorldProviderImpl", 100 | "interface_name": "dojo::world::world_contract::IWorldProvider" 101 | }, 102 | { 103 | "type": "struct", 104 | "name": "dojo::world::world_contract::IWorldDispatcher", 105 | "members": [ 106 | { 107 | "name": "contract_address", 108 | "type": "core::starknet::contract_address::ContractAddress" 109 | } 110 | ] 111 | }, 112 | { 113 | "type": "interface", 114 | "name": "dojo::world::world_contract::IWorldProvider", 115 | "items": [ 116 | { 117 | "type": "function", 118 | "name": "world", 119 | "inputs": [], 120 | "outputs": [ 121 | { 122 | "type": "dojo::world::world_contract::IWorldDispatcher" 123 | } 124 | ], 125 | "state_mutability": "view" 126 | } 127 | ] 128 | }, 129 | { 130 | "type": "impl", 131 | "name": "SpawnActionImpl", 132 | "interface_name": "bytebeasts::systems::spawn::ISpawnAction" 133 | }, 134 | { 135 | "type": "interface", 136 | "name": "bytebeasts::systems::spawn::ISpawnAction", 137 | "items": [ 138 | { 139 | "type": "function", 140 | "name": "spawn", 141 | "inputs": [ 142 | { 143 | "name": "player_id", 144 | "type": "core::integer::u32" 145 | } 146 | ], 147 | "outputs": [], 148 | "state_mutability": "external" 149 | } 150 | ] 151 | }, 152 | { 153 | "type": "impl", 154 | "name": "IDojoInitImpl", 155 | "interface_name": "bytebeasts::systems::spawn::spawn_action::IDojoInit" 156 | }, 157 | { 158 | "type": "interface", 159 | "name": "bytebeasts::systems::spawn::spawn_action::IDojoInit", 160 | "items": [ 161 | { 162 | "type": "function", 163 | "name": "dojo_init", 164 | "inputs": [], 165 | "outputs": [], 166 | "state_mutability": "view" 167 | } 168 | ] 169 | }, 170 | { 171 | "type": "impl", 172 | "name": "UpgradableImpl", 173 | "interface_name": "dojo::contract::upgradeable::IUpgradeable" 174 | }, 175 | { 176 | "type": "interface", 177 | "name": "dojo::contract::upgradeable::IUpgradeable", 178 | "items": [ 179 | { 180 | "type": "function", 181 | "name": "upgrade", 182 | "inputs": [ 183 | { 184 | "name": "new_class_hash", 185 | "type": "core::starknet::class_hash::ClassHash" 186 | } 187 | ], 188 | "outputs": [], 189 | "state_mutability": "external" 190 | } 191 | ] 192 | }, 193 | { 194 | "type": "event", 195 | "name": "dojo::contract::upgradeable::upgradeable::Upgraded", 196 | "kind": "struct", 197 | "members": [ 198 | { 199 | "name": "class_hash", 200 | "type": "core::starknet::class_hash::ClassHash", 201 | "kind": "data" 202 | } 203 | ] 204 | }, 205 | { 206 | "type": "event", 207 | "name": "dojo::contract::upgradeable::upgradeable::Event", 208 | "kind": "enum", 209 | "variants": [ 210 | { 211 | "name": "Upgraded", 212 | "type": "dojo::contract::upgradeable::upgradeable::Upgraded", 213 | "kind": "nested" 214 | } 215 | ] 216 | }, 217 | { 218 | "type": "event", 219 | "name": "bytebeasts::systems::spawn::spawn_action::Event", 220 | "kind": "enum", 221 | "variants": [ 222 | { 223 | "name": "UpgradeableEvent", 224 | "type": "dojo::contract::upgradeable::upgradeable::Event", 225 | "kind": "nested" 226 | } 227 | ] 228 | } 229 | ] -------------------------------------------------------------------------------- /manifests/dev/deployment/abis/contracts/bytebeasts-spawn_action-5176c1e8.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "impl", 4 | "name": "ContractImpl", 5 | "interface_name": "dojo::contract::contract::IContract" 6 | }, 7 | { 8 | "type": "struct", 9 | "name": "core::byte_array::ByteArray", 10 | "members": [ 11 | { 12 | "name": "data", 13 | "type": "core::array::Array::" 14 | }, 15 | { 16 | "name": "pending_word", 17 | "type": "core::felt252" 18 | }, 19 | { 20 | "name": "pending_word_len", 21 | "type": "core::integer::u32" 22 | } 23 | ] 24 | }, 25 | { 26 | "type": "interface", 27 | "name": "dojo::contract::contract::IContract", 28 | "items": [ 29 | { 30 | "type": "function", 31 | "name": "contract_name", 32 | "inputs": [], 33 | "outputs": [ 34 | { 35 | "type": "core::byte_array::ByteArray" 36 | } 37 | ], 38 | "state_mutability": "view" 39 | }, 40 | { 41 | "type": "function", 42 | "name": "namespace", 43 | "inputs": [], 44 | "outputs": [ 45 | { 46 | "type": "core::byte_array::ByteArray" 47 | } 48 | ], 49 | "state_mutability": "view" 50 | }, 51 | { 52 | "type": "function", 53 | "name": "tag", 54 | "inputs": [], 55 | "outputs": [ 56 | { 57 | "type": "core::byte_array::ByteArray" 58 | } 59 | ], 60 | "state_mutability": "view" 61 | }, 62 | { 63 | "type": "function", 64 | "name": "name_hash", 65 | "inputs": [], 66 | "outputs": [ 67 | { 68 | "type": "core::felt252" 69 | } 70 | ], 71 | "state_mutability": "view" 72 | }, 73 | { 74 | "type": "function", 75 | "name": "namespace_hash", 76 | "inputs": [], 77 | "outputs": [ 78 | { 79 | "type": "core::felt252" 80 | } 81 | ], 82 | "state_mutability": "view" 83 | }, 84 | { 85 | "type": "function", 86 | "name": "selector", 87 | "inputs": [], 88 | "outputs": [ 89 | { 90 | "type": "core::felt252" 91 | } 92 | ], 93 | "state_mutability": "view" 94 | } 95 | ] 96 | }, 97 | { 98 | "type": "impl", 99 | "name": "WorldProviderImpl", 100 | "interface_name": "dojo::world::world_contract::IWorldProvider" 101 | }, 102 | { 103 | "type": "struct", 104 | "name": "dojo::world::world_contract::IWorldDispatcher", 105 | "members": [ 106 | { 107 | "name": "contract_address", 108 | "type": "core::starknet::contract_address::ContractAddress" 109 | } 110 | ] 111 | }, 112 | { 113 | "type": "interface", 114 | "name": "dojo::world::world_contract::IWorldProvider", 115 | "items": [ 116 | { 117 | "type": "function", 118 | "name": "world", 119 | "inputs": [], 120 | "outputs": [ 121 | { 122 | "type": "dojo::world::world_contract::IWorldDispatcher" 123 | } 124 | ], 125 | "state_mutability": "view" 126 | } 127 | ] 128 | }, 129 | { 130 | "type": "impl", 131 | "name": "SpawnActionImpl", 132 | "interface_name": "bytebeasts::systems::spawn::ISpawnAction" 133 | }, 134 | { 135 | "type": "interface", 136 | "name": "bytebeasts::systems::spawn::ISpawnAction", 137 | "items": [ 138 | { 139 | "type": "function", 140 | "name": "spawn", 141 | "inputs": [ 142 | { 143 | "name": "player_id", 144 | "type": "core::integer::u32" 145 | } 146 | ], 147 | "outputs": [], 148 | "state_mutability": "external" 149 | } 150 | ] 151 | }, 152 | { 153 | "type": "impl", 154 | "name": "IDojoInitImpl", 155 | "interface_name": "bytebeasts::systems::spawn::spawn_action::IDojoInit" 156 | }, 157 | { 158 | "type": "interface", 159 | "name": "bytebeasts::systems::spawn::spawn_action::IDojoInit", 160 | "items": [ 161 | { 162 | "type": "function", 163 | "name": "dojo_init", 164 | "inputs": [], 165 | "outputs": [], 166 | "state_mutability": "view" 167 | } 168 | ] 169 | }, 170 | { 171 | "type": "impl", 172 | "name": "UpgradableImpl", 173 | "interface_name": "dojo::contract::upgradeable::IUpgradeable" 174 | }, 175 | { 176 | "type": "interface", 177 | "name": "dojo::contract::upgradeable::IUpgradeable", 178 | "items": [ 179 | { 180 | "type": "function", 181 | "name": "upgrade", 182 | "inputs": [ 183 | { 184 | "name": "new_class_hash", 185 | "type": "core::starknet::class_hash::ClassHash" 186 | } 187 | ], 188 | "outputs": [], 189 | "state_mutability": "external" 190 | } 191 | ] 192 | }, 193 | { 194 | "type": "event", 195 | "name": "dojo::contract::upgradeable::upgradeable::Upgraded", 196 | "kind": "struct", 197 | "members": [ 198 | { 199 | "name": "class_hash", 200 | "type": "core::starknet::class_hash::ClassHash", 201 | "kind": "data" 202 | } 203 | ] 204 | }, 205 | { 206 | "type": "event", 207 | "name": "dojo::contract::upgradeable::upgradeable::Event", 208 | "kind": "enum", 209 | "variants": [ 210 | { 211 | "name": "Upgraded", 212 | "type": "dojo::contract::upgradeable::upgradeable::Upgraded", 213 | "kind": "nested" 214 | } 215 | ] 216 | }, 217 | { 218 | "type": "event", 219 | "name": "bytebeasts::systems::spawn::spawn_action::Event", 220 | "kind": "enum", 221 | "variants": [ 222 | { 223 | "name": "UpgradeableEvent", 224 | "type": "dojo::contract::upgradeable::upgradeable::Event", 225 | "kind": "nested" 226 | } 227 | ] 228 | } 229 | ] -------------------------------------------------------------------------------- /src/systems/leaderboard.cairo: -------------------------------------------------------------------------------- 1 | use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; 2 | use bytebeasts::models::leaderboard::{Leaderboard, LeaderboardEntry, LeaderboardTrait}; 3 | use alexandria_data_structures::array_ext::ArrayTraitExt; 4 | 5 | #[dojo::interface] 6 | trait ILeaderboardAction { 7 | fn create_leaderboard( 8 | ref world: IWorldDispatcher, 9 | leaderboard_id: u64, 10 | name: felt252, 11 | description: felt252, 12 | last_updated: u64, 13 | ); 14 | 15 | fn add_entry( 16 | ref world: IWorldDispatcher, 17 | leaderboard_id: u64, 18 | player_id: u32, 19 | player_name: felt252, 20 | score: u32, 21 | wins: u32, 22 | losses: u32, 23 | highest_score: u32, 24 | is_active: bool, 25 | ); 26 | 27 | fn get_all_entries(ref world: IWorldDispatcher, leaderboard_id: u64) -> Array; 28 | 29 | fn remove_entry(ref world: IWorldDispatcher, leaderboard_id: u64, player_id: u32); 30 | 31 | fn update_entry( 32 | ref world: IWorldDispatcher, 33 | leaderboard_id: u64, 34 | player_id: u32, 35 | player_name: felt252, 36 | score: u32, 37 | wins: u32, 38 | losses: u32, 39 | highest_score: u32, 40 | is_active: bool, 41 | ); 42 | 43 | fn calculate_score(wins: u32, highest_score: u32, losses: u32) -> u32; 44 | 45 | fn get_slice( 46 | ref world: IWorldDispatcher, 47 | leaderboard_id: u64, 48 | start: u32, 49 | end: u32, 50 | ) -> Array; 51 | 52 | fn upgrade_entry_stats( 53 | ref world: IWorldDispatcher, 54 | leaderboard_id: u64, 55 | player_id: u32, 56 | new_wins: u32, 57 | new_losses: u32, 58 | new_highest_score: u32, 59 | ); 60 | } 61 | 62 | #[dojo::contract] 63 | mod leaderboard_system { 64 | use super::ILeaderboardAction; 65 | use bytebeasts::models::leaderboard::{Leaderboard, LeaderboardEntry, LeaderboardTrait}; 66 | 67 | #[abi(embed_v0)] 68 | impl LeaderboardActionImpl of ILeaderboardAction { 69 | fn create_leaderboard( 70 | ref world: IWorldDispatcher, 71 | leaderboard_id: u64, 72 | name: felt252, 73 | description: felt252, 74 | last_updated: u64, 75 | ) { 76 | let leaderboard = Leaderboard { 77 | leaderboard_id, 78 | name, 79 | description, 80 | entries: array![], 81 | last_updated, 82 | }; 83 | set!(world, (leaderboard)); 84 | } 85 | 86 | fn add_entry( 87 | ref world: IWorldDispatcher, 88 | leaderboard_id: u64, 89 | player_id: u32, 90 | player_name: felt252, 91 | score: u32, 92 | wins: u32, 93 | losses: u32, 94 | highest_score: u32, 95 | is_active: bool, 96 | ) { 97 | let mut leaderboard = get!(world, leaderboard_id, Leaderboard); 98 | let entry = LeaderboardEntry { 99 | player_id, 100 | player_name, 101 | score, 102 | wins, 103 | losses, 104 | highest_score, 105 | is_active, 106 | }; 107 | leaderboard.add_entry(entry).unwrap(); 108 | set!(world, (leaderboard)); 109 | } 110 | 111 | fn get_all_entries(ref world: IWorldDispatcher, leaderboard_id: u64) -> Array { 112 | let mut leaderboard = get!(world, leaderboard_id, Leaderboard); 113 | leaderboard.get_entries() 114 | } 115 | 116 | fn remove_entry(ref world: IWorldDispatcher, leaderboard_id: u64, player_id: u32) { 117 | let mut leaderboard = get!(world, leaderboard_id, Leaderboard); 118 | let index = leaderboard.get_index_by_player_id(player_id).unwrap(); 119 | let entry = leaderboard.entries.at(index); 120 | leaderboard.remove_entry(*entry).unwrap(); 121 | set!(world, (leaderboard)); 122 | } 123 | 124 | fn update_entry( 125 | ref world: IWorldDispatcher, 126 | leaderboard_id: u64, 127 | player_id: u32, 128 | player_name: felt252, 129 | score: u32, 130 | wins: u32, 131 | losses: u32, 132 | highest_score: u32, 133 | is_active: bool, 134 | ) { 135 | let mut leaderboard = get!(world, leaderboard_id, Leaderboard); 136 | let entry = LeaderboardEntry { 137 | player_id, 138 | player_name, 139 | score, 140 | wins, 141 | losses, 142 | highest_score, 143 | is_active, 144 | }; 145 | leaderboard.update_entry(entry).unwrap(); 146 | set!(world, (leaderboard)); 147 | } 148 | 149 | fn calculate_score(wins: u32, highest_score: u32, losses: u32) -> u32 { 150 | wins * 100 + highest_score - losses * 70 151 | } 152 | 153 | fn get_slice( 154 | ref world: IWorldDispatcher, 155 | leaderboard_id: u64, 156 | start: u32, 157 | end: u32, 158 | ) -> Array { 159 | let mut leaderboard = get!(world, leaderboard_id, Leaderboard); 160 | leaderboard.get_slice(start, end).unwrap() 161 | } 162 | 163 | fn upgrade_entry_stats( 164 | ref world: IWorldDispatcher, 165 | leaderboard_id: u64, 166 | player_id: u32, 167 | new_wins: u32, 168 | new_losses: u32, 169 | new_highest_score: u32, 170 | ) { 171 | let mut leaderboard = get!(world, leaderboard_id, Leaderboard); 172 | leaderboard 173 | .upgrade_entry_stats(player_id, new_wins, new_losses, new_highest_score) 174 | .unwrap(); 175 | set!(world, (leaderboard)); 176 | } 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /manifests/dev/base/abis/contracts/bytebeasts-move_action-62decdb8.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "impl", 4 | "name": "ContractImpl", 5 | "interface_name": "dojo::contract::contract::IContract" 6 | }, 7 | { 8 | "type": "struct", 9 | "name": "core::byte_array::ByteArray", 10 | "members": [ 11 | { 12 | "name": "data", 13 | "type": "core::array::Array::" 14 | }, 15 | { 16 | "name": "pending_word", 17 | "type": "core::felt252" 18 | }, 19 | { 20 | "name": "pending_word_len", 21 | "type": "core::integer::u32" 22 | } 23 | ] 24 | }, 25 | { 26 | "type": "interface", 27 | "name": "dojo::contract::contract::IContract", 28 | "items": [ 29 | { 30 | "type": "function", 31 | "name": "contract_name", 32 | "inputs": [], 33 | "outputs": [ 34 | { 35 | "type": "core::byte_array::ByteArray" 36 | } 37 | ], 38 | "state_mutability": "view" 39 | }, 40 | { 41 | "type": "function", 42 | "name": "namespace", 43 | "inputs": [], 44 | "outputs": [ 45 | { 46 | "type": "core::byte_array::ByteArray" 47 | } 48 | ], 49 | "state_mutability": "view" 50 | }, 51 | { 52 | "type": "function", 53 | "name": "tag", 54 | "inputs": [], 55 | "outputs": [ 56 | { 57 | "type": "core::byte_array::ByteArray" 58 | } 59 | ], 60 | "state_mutability": "view" 61 | }, 62 | { 63 | "type": "function", 64 | "name": "name_hash", 65 | "inputs": [], 66 | "outputs": [ 67 | { 68 | "type": "core::felt252" 69 | } 70 | ], 71 | "state_mutability": "view" 72 | }, 73 | { 74 | "type": "function", 75 | "name": "namespace_hash", 76 | "inputs": [], 77 | "outputs": [ 78 | { 79 | "type": "core::felt252" 80 | } 81 | ], 82 | "state_mutability": "view" 83 | }, 84 | { 85 | "type": "function", 86 | "name": "selector", 87 | "inputs": [], 88 | "outputs": [ 89 | { 90 | "type": "core::felt252" 91 | } 92 | ], 93 | "state_mutability": "view" 94 | } 95 | ] 96 | }, 97 | { 98 | "type": "impl", 99 | "name": "WorldProviderImpl", 100 | "interface_name": "dojo::world::world_contract::IWorldProvider" 101 | }, 102 | { 103 | "type": "struct", 104 | "name": "dojo::world::world_contract::IWorldDispatcher", 105 | "members": [ 106 | { 107 | "name": "contract_address", 108 | "type": "core::starknet::contract_address::ContractAddress" 109 | } 110 | ] 111 | }, 112 | { 113 | "type": "interface", 114 | "name": "dojo::world::world_contract::IWorldProvider", 115 | "items": [ 116 | { 117 | "type": "function", 118 | "name": "world", 119 | "inputs": [], 120 | "outputs": [ 121 | { 122 | "type": "dojo::world::world_contract::IWorldDispatcher" 123 | } 124 | ], 125 | "state_mutability": "view" 126 | } 127 | ] 128 | }, 129 | { 130 | "type": "impl", 131 | "name": "MoveActionImpl", 132 | "interface_name": "bytebeasts::systems::move::IMoveAction" 133 | }, 134 | { 135 | "type": "interface", 136 | "name": "bytebeasts::systems::move::IMoveAction", 137 | "items": [ 138 | { 139 | "type": "function", 140 | "name": "move", 141 | "inputs": [ 142 | { 143 | "name": "player_id", 144 | "type": "core::integer::u32" 145 | }, 146 | { 147 | "name": "new_x", 148 | "type": "core::integer::u32" 149 | }, 150 | { 151 | "name": "new_y", 152 | "type": "core::integer::u32" 153 | } 154 | ], 155 | "outputs": [], 156 | "state_mutability": "external" 157 | } 158 | ] 159 | }, 160 | { 161 | "type": "impl", 162 | "name": "IDojoInitImpl", 163 | "interface_name": "bytebeasts::systems::move::move_action::IDojoInit" 164 | }, 165 | { 166 | "type": "interface", 167 | "name": "bytebeasts::systems::move::move_action::IDojoInit", 168 | "items": [ 169 | { 170 | "type": "function", 171 | "name": "dojo_init", 172 | "inputs": [], 173 | "outputs": [], 174 | "state_mutability": "view" 175 | } 176 | ] 177 | }, 178 | { 179 | "type": "impl", 180 | "name": "UpgradableImpl", 181 | "interface_name": "dojo::contract::upgradeable::IUpgradeable" 182 | }, 183 | { 184 | "type": "interface", 185 | "name": "dojo::contract::upgradeable::IUpgradeable", 186 | "items": [ 187 | { 188 | "type": "function", 189 | "name": "upgrade", 190 | "inputs": [ 191 | { 192 | "name": "new_class_hash", 193 | "type": "core::starknet::class_hash::ClassHash" 194 | } 195 | ], 196 | "outputs": [], 197 | "state_mutability": "external" 198 | } 199 | ] 200 | }, 201 | { 202 | "type": "event", 203 | "name": "dojo::contract::upgradeable::upgradeable::Upgraded", 204 | "kind": "struct", 205 | "members": [ 206 | { 207 | "name": "class_hash", 208 | "type": "core::starknet::class_hash::ClassHash", 209 | "kind": "data" 210 | } 211 | ] 212 | }, 213 | { 214 | "type": "event", 215 | "name": "dojo::contract::upgradeable::upgradeable::Event", 216 | "kind": "enum", 217 | "variants": [ 218 | { 219 | "name": "Upgraded", 220 | "type": "dojo::contract::upgradeable::upgradeable::Upgraded", 221 | "kind": "nested" 222 | } 223 | ] 224 | }, 225 | { 226 | "type": "event", 227 | "name": "bytebeasts::systems::move::move_action::Event", 228 | "kind": "enum", 229 | "variants": [ 230 | { 231 | "name": "UpgradeableEvent", 232 | "type": "dojo::contract::upgradeable::upgradeable::Event", 233 | "kind": "nested" 234 | } 235 | ] 236 | } 237 | ] -------------------------------------------------------------------------------- /manifests/dev/deployment/abis/contracts/bytebeasts-move_action-62decdb8.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "impl", 4 | "name": "ContractImpl", 5 | "interface_name": "dojo::contract::contract::IContract" 6 | }, 7 | { 8 | "type": "struct", 9 | "name": "core::byte_array::ByteArray", 10 | "members": [ 11 | { 12 | "name": "data", 13 | "type": "core::array::Array::" 14 | }, 15 | { 16 | "name": "pending_word", 17 | "type": "core::felt252" 18 | }, 19 | { 20 | "name": "pending_word_len", 21 | "type": "core::integer::u32" 22 | } 23 | ] 24 | }, 25 | { 26 | "type": "interface", 27 | "name": "dojo::contract::contract::IContract", 28 | "items": [ 29 | { 30 | "type": "function", 31 | "name": "contract_name", 32 | "inputs": [], 33 | "outputs": [ 34 | { 35 | "type": "core::byte_array::ByteArray" 36 | } 37 | ], 38 | "state_mutability": "view" 39 | }, 40 | { 41 | "type": "function", 42 | "name": "namespace", 43 | "inputs": [], 44 | "outputs": [ 45 | { 46 | "type": "core::byte_array::ByteArray" 47 | } 48 | ], 49 | "state_mutability": "view" 50 | }, 51 | { 52 | "type": "function", 53 | "name": "tag", 54 | "inputs": [], 55 | "outputs": [ 56 | { 57 | "type": "core::byte_array::ByteArray" 58 | } 59 | ], 60 | "state_mutability": "view" 61 | }, 62 | { 63 | "type": "function", 64 | "name": "name_hash", 65 | "inputs": [], 66 | "outputs": [ 67 | { 68 | "type": "core::felt252" 69 | } 70 | ], 71 | "state_mutability": "view" 72 | }, 73 | { 74 | "type": "function", 75 | "name": "namespace_hash", 76 | "inputs": [], 77 | "outputs": [ 78 | { 79 | "type": "core::felt252" 80 | } 81 | ], 82 | "state_mutability": "view" 83 | }, 84 | { 85 | "type": "function", 86 | "name": "selector", 87 | "inputs": [], 88 | "outputs": [ 89 | { 90 | "type": "core::felt252" 91 | } 92 | ], 93 | "state_mutability": "view" 94 | } 95 | ] 96 | }, 97 | { 98 | "type": "impl", 99 | "name": "WorldProviderImpl", 100 | "interface_name": "dojo::world::world_contract::IWorldProvider" 101 | }, 102 | { 103 | "type": "struct", 104 | "name": "dojo::world::world_contract::IWorldDispatcher", 105 | "members": [ 106 | { 107 | "name": "contract_address", 108 | "type": "core::starknet::contract_address::ContractAddress" 109 | } 110 | ] 111 | }, 112 | { 113 | "type": "interface", 114 | "name": "dojo::world::world_contract::IWorldProvider", 115 | "items": [ 116 | { 117 | "type": "function", 118 | "name": "world", 119 | "inputs": [], 120 | "outputs": [ 121 | { 122 | "type": "dojo::world::world_contract::IWorldDispatcher" 123 | } 124 | ], 125 | "state_mutability": "view" 126 | } 127 | ] 128 | }, 129 | { 130 | "type": "impl", 131 | "name": "MoveActionImpl", 132 | "interface_name": "bytebeasts::systems::move::IMoveAction" 133 | }, 134 | { 135 | "type": "interface", 136 | "name": "bytebeasts::systems::move::IMoveAction", 137 | "items": [ 138 | { 139 | "type": "function", 140 | "name": "move", 141 | "inputs": [ 142 | { 143 | "name": "player_id", 144 | "type": "core::integer::u32" 145 | }, 146 | { 147 | "name": "new_x", 148 | "type": "core::integer::u32" 149 | }, 150 | { 151 | "name": "new_y", 152 | "type": "core::integer::u32" 153 | } 154 | ], 155 | "outputs": [], 156 | "state_mutability": "external" 157 | } 158 | ] 159 | }, 160 | { 161 | "type": "impl", 162 | "name": "IDojoInitImpl", 163 | "interface_name": "bytebeasts::systems::move::move_action::IDojoInit" 164 | }, 165 | { 166 | "type": "interface", 167 | "name": "bytebeasts::systems::move::move_action::IDojoInit", 168 | "items": [ 169 | { 170 | "type": "function", 171 | "name": "dojo_init", 172 | "inputs": [], 173 | "outputs": [], 174 | "state_mutability": "view" 175 | } 176 | ] 177 | }, 178 | { 179 | "type": "impl", 180 | "name": "UpgradableImpl", 181 | "interface_name": "dojo::contract::upgradeable::IUpgradeable" 182 | }, 183 | { 184 | "type": "interface", 185 | "name": "dojo::contract::upgradeable::IUpgradeable", 186 | "items": [ 187 | { 188 | "type": "function", 189 | "name": "upgrade", 190 | "inputs": [ 191 | { 192 | "name": "new_class_hash", 193 | "type": "core::starknet::class_hash::ClassHash" 194 | } 195 | ], 196 | "outputs": [], 197 | "state_mutability": "external" 198 | } 199 | ] 200 | }, 201 | { 202 | "type": "event", 203 | "name": "dojo::contract::upgradeable::upgradeable::Upgraded", 204 | "kind": "struct", 205 | "members": [ 206 | { 207 | "name": "class_hash", 208 | "type": "core::starknet::class_hash::ClassHash", 209 | "kind": "data" 210 | } 211 | ] 212 | }, 213 | { 214 | "type": "event", 215 | "name": "dojo::contract::upgradeable::upgradeable::Event", 216 | "kind": "enum", 217 | "variants": [ 218 | { 219 | "name": "Upgraded", 220 | "type": "dojo::contract::upgradeable::upgradeable::Upgraded", 221 | "kind": "nested" 222 | } 223 | ] 224 | }, 225 | { 226 | "type": "event", 227 | "name": "bytebeasts::systems::move::move_action::Event", 228 | "kind": "enum", 229 | "variants": [ 230 | { 231 | "name": "UpgradeableEvent", 232 | "type": "dojo::contract::upgradeable::upgradeable::Event", 233 | "kind": "nested" 234 | } 235 | ] 236 | } 237 | ] -------------------------------------------------------------------------------- /src/systems/world_setup.cairo: -------------------------------------------------------------------------------- 1 | use bytebeasts::{ 2 | models::{ 3 | beast::Beast, mt::Mt, player::Player, coordinates::Coordinates, position::Position, 4 | potion::Potion, world_elements::WorldElements 5 | }, 6 | }; 7 | 8 | #[dojo::interface] 9 | trait IWorldSetup { 10 | fn setWorld(ref world: IWorldDispatcher); 11 | } 12 | 13 | #[dojo::contract] 14 | mod world_setup { 15 | use super::IWorldSetup; 16 | use starknet::{ContractAddress, get_caller_address}; 17 | use bytebeasts::{ 18 | models::{ 19 | beast::Beast, mt::Mt, player::Player, coordinates::Coordinates, position::Position, 20 | potion::Potion, world_elements::WorldElements 21 | }, 22 | }; 23 | 24 | #[abi(embed_v0)] 25 | impl WorldSetupImpl of IWorldSetup { 26 | fn setWorld(ref world: IWorldDispatcher) { 27 | // Set Beasts 28 | set!( 29 | world, 30 | (Beast { 31 | beast_id: 1, 32 | beast_name: 'Firebeast', 33 | beast_type: WorldElements::Draconic(()), 34 | beast_description: 'A fiery beast.', 35 | player_id: 1, 36 | hp: 100, 37 | current_hp: 100, 38 | attack: 50, 39 | defense: 40, 40 | mt1: 1, // Fire Blast 41 | mt2: 2, // Ember 42 | mt3: 3, // Flame Wheel 43 | mt4: 4, // Fire Punch 44 | level: 5, 45 | experience_to_next_level: 1000 46 | }) 47 | ); 48 | 49 | set!( 50 | world, 51 | (Beast { 52 | beast_id: 2, 53 | beast_name: 'Aqua', 54 | beast_type: WorldElements::Crystal(()), 55 | beast_description: 'A water beast', 56 | player_id: 2, 57 | hp: 110, 58 | current_hp: 110, 59 | attack: 45, 60 | defense: 50, 61 | mt1: 5, // Water Gun 62 | mt2: 6, // Bubble 63 | mt3: 7, // Aqua Tail 64 | mt4: 8, // Hydro Pump 65 | level: 5, 66 | experience_to_next_level: 1000 67 | }) 68 | ); 69 | 70 | // Set Trainers 71 | set!( 72 | world, 73 | (Player { 74 | player_id: 1, 75 | player_name: 'Ash', 76 | beast_1: 1, // Hellooo 77 | beast_2: 0, // No beast assigned 78 | beast_3: 0, // No beast assigned 79 | beast_4: 0, // No beast assigned 80 | potions: 2 81 | }) 82 | ); 83 | 84 | set!( 85 | world, 86 | (Player { 87 | player_id: 2, 88 | player_name: 'Misty', 89 | beast_1: 2, // Aqua 90 | beast_2: 0, // No beast assigned 91 | beast_3: 0, // No beast assigned 92 | beast_4: 0, // No beast assigned 93 | potions: 3 94 | }) 95 | ); 96 | 97 | // Set Potions 98 | set!(world, (Potion { potion_id: 1, potion_name: 'Health Potion', potion_effect: 50 })); 99 | set!(world, (Potion { potion_id: 2, potion_name: 'Super Potion', potion_effect: 100 })); 100 | 101 | // Set Mts 102 | set!( 103 | world, 104 | (Mt { 105 | mt_id: 1, 106 | mt_name: 'Fire Blast', 107 | mt_type: WorldElements::Draconic(()), 108 | mt_power: 90, 109 | mt_accuracy: 85 110 | }) 111 | ); 112 | 113 | set!( 114 | world, 115 | (Mt { 116 | mt_id: 2, 117 | mt_name: 'Ember', 118 | mt_type: WorldElements::Crystal(()), 119 | mt_power: 40, 120 | mt_accuracy: 100 121 | }) 122 | ); 123 | 124 | set!( 125 | world, 126 | (Mt { 127 | mt_id: 3, 128 | mt_name: 'Flame Wheel', 129 | mt_type: WorldElements::Draconic(()), 130 | mt_power: 60, 131 | mt_accuracy: 95 132 | }) 133 | ); 134 | 135 | set!( 136 | world, 137 | (Mt { 138 | mt_id: 4, 139 | mt_name: 'Fire Punch', 140 | mt_type: WorldElements::Crystal(()), 141 | mt_power: 75, 142 | mt_accuracy: 100 143 | }) 144 | ); 145 | 146 | set!( 147 | world, 148 | (Mt { 149 | mt_id: 5, 150 | mt_name: 'Water Gun', 151 | mt_type: WorldElements::Crystal(()), 152 | mt_power: 40, 153 | mt_accuracy: 100 154 | }) 155 | ); 156 | 157 | set!( 158 | world, 159 | (Mt { 160 | mt_id: 6, 161 | mt_name: 'Bubble', 162 | mt_type: WorldElements::Draconic(()), 163 | mt_power: 20, 164 | mt_accuracy: 100 165 | }) 166 | ); 167 | 168 | set!( 169 | world, 170 | (Mt { 171 | mt_id: 7, 172 | mt_name: 'Aqua Tail', 173 | mt_type: WorldElements::Crystal(()), 174 | mt_power: 90, 175 | mt_accuracy: 90 176 | }) 177 | ); 178 | 179 | set!( 180 | world, 181 | (Mt { 182 | mt_id: 8, 183 | mt_name: 'Hydro Pump', 184 | mt_type: WorldElements::Crystal(()), 185 | mt_power: 110, 186 | mt_accuracy: 80 187 | }) 188 | ); 189 | } 190 | } 191 | } -------------------------------------------------------------------------------- /manifests/dev/base/abis/contracts/bytebeasts-bag_system-7ad8a155.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "impl", 4 | "name": "ContractImpl", 5 | "interface_name": "dojo::contract::contract::IContract" 6 | }, 7 | { 8 | "type": "struct", 9 | "name": "core::byte_array::ByteArray", 10 | "members": [ 11 | { 12 | "name": "data", 13 | "type": "core::array::Array::" 14 | }, 15 | { 16 | "name": "pending_word", 17 | "type": "core::felt252" 18 | }, 19 | { 20 | "name": "pending_word_len", 21 | "type": "core::integer::u32" 22 | } 23 | ] 24 | }, 25 | { 26 | "type": "interface", 27 | "name": "dojo::contract::contract::IContract", 28 | "items": [ 29 | { 30 | "type": "function", 31 | "name": "contract_name", 32 | "inputs": [], 33 | "outputs": [ 34 | { 35 | "type": "core::byte_array::ByteArray" 36 | } 37 | ], 38 | "state_mutability": "view" 39 | }, 40 | { 41 | "type": "function", 42 | "name": "namespace", 43 | "inputs": [], 44 | "outputs": [ 45 | { 46 | "type": "core::byte_array::ByteArray" 47 | } 48 | ], 49 | "state_mutability": "view" 50 | }, 51 | { 52 | "type": "function", 53 | "name": "tag", 54 | "inputs": [], 55 | "outputs": [ 56 | { 57 | "type": "core::byte_array::ByteArray" 58 | } 59 | ], 60 | "state_mutability": "view" 61 | }, 62 | { 63 | "type": "function", 64 | "name": "name_hash", 65 | "inputs": [], 66 | "outputs": [ 67 | { 68 | "type": "core::felt252" 69 | } 70 | ], 71 | "state_mutability": "view" 72 | }, 73 | { 74 | "type": "function", 75 | "name": "namespace_hash", 76 | "inputs": [], 77 | "outputs": [ 78 | { 79 | "type": "core::felt252" 80 | } 81 | ], 82 | "state_mutability": "view" 83 | }, 84 | { 85 | "type": "function", 86 | "name": "selector", 87 | "inputs": [], 88 | "outputs": [ 89 | { 90 | "type": "core::felt252" 91 | } 92 | ], 93 | "state_mutability": "view" 94 | } 95 | ] 96 | }, 97 | { 98 | "type": "impl", 99 | "name": "WorldProviderImpl", 100 | "interface_name": "dojo::world::world_contract::IWorldProvider" 101 | }, 102 | { 103 | "type": "struct", 104 | "name": "dojo::world::world_contract::IWorldDispatcher", 105 | "members": [ 106 | { 107 | "name": "contract_address", 108 | "type": "core::starknet::contract_address::ContractAddress" 109 | } 110 | ] 111 | }, 112 | { 113 | "type": "interface", 114 | "name": "dojo::world::world_contract::IWorldProvider", 115 | "items": [ 116 | { 117 | "type": "function", 118 | "name": "world", 119 | "inputs": [], 120 | "outputs": [ 121 | { 122 | "type": "dojo::world::world_contract::IWorldDispatcher" 123 | } 124 | ], 125 | "state_mutability": "view" 126 | } 127 | ] 128 | }, 129 | { 130 | "type": "impl", 131 | "name": "BagActionImpl", 132 | "interface_name": "bytebeasts::systems::bag::IBagAction" 133 | }, 134 | { 135 | "type": "struct", 136 | "name": "bytebeasts::models::potion::Potion", 137 | "members": [ 138 | { 139 | "name": "potion_id", 140 | "type": "core::integer::u32" 141 | }, 142 | { 143 | "name": "potion_name", 144 | "type": "core::felt252" 145 | }, 146 | { 147 | "name": "potion_effect", 148 | "type": "core::integer::u32" 149 | } 150 | ] 151 | }, 152 | { 153 | "type": "interface", 154 | "name": "bytebeasts::systems::bag::IBagAction", 155 | "items": [ 156 | { 157 | "type": "function", 158 | "name": "init_bag", 159 | "inputs": [ 160 | { 161 | "name": "bag_id", 162 | "type": "core::integer::u32" 163 | }, 164 | { 165 | "name": "player_id", 166 | "type": "core::integer::u32" 167 | } 168 | ], 169 | "outputs": [], 170 | "state_mutability": "external" 171 | }, 172 | { 173 | "type": "function", 174 | "name": "add_item", 175 | "inputs": [ 176 | { 177 | "name": "player_id", 178 | "type": "core::integer::u32" 179 | }, 180 | { 181 | "name": "bag_id", 182 | "type": "core::integer::u32" 183 | }, 184 | { 185 | "name": "potion", 186 | "type": "bytebeasts::models::potion::Potion" 187 | } 188 | ], 189 | "outputs": [], 190 | "state_mutability": "external" 191 | }, 192 | { 193 | "type": "function", 194 | "name": "take_out_item", 195 | "inputs": [ 196 | { 197 | "name": "player_id", 198 | "type": "core::integer::u32" 199 | }, 200 | { 201 | "name": "bag_id", 202 | "type": "core::integer::u32" 203 | } 204 | ], 205 | "outputs": [ 206 | { 207 | "type": "bytebeasts::models::potion::Potion" 208 | } 209 | ], 210 | "state_mutability": "external" 211 | } 212 | ] 213 | }, 214 | { 215 | "type": "impl", 216 | "name": "IDojoInitImpl", 217 | "interface_name": "bytebeasts::systems::bag::bag_system::IDojoInit" 218 | }, 219 | { 220 | "type": "interface", 221 | "name": "bytebeasts::systems::bag::bag_system::IDojoInit", 222 | "items": [ 223 | { 224 | "type": "function", 225 | "name": "dojo_init", 226 | "inputs": [], 227 | "outputs": [], 228 | "state_mutability": "view" 229 | } 230 | ] 231 | }, 232 | { 233 | "type": "impl", 234 | "name": "UpgradableImpl", 235 | "interface_name": "dojo::contract::upgradeable::IUpgradeable" 236 | }, 237 | { 238 | "type": "interface", 239 | "name": "dojo::contract::upgradeable::IUpgradeable", 240 | "items": [ 241 | { 242 | "type": "function", 243 | "name": "upgrade", 244 | "inputs": [ 245 | { 246 | "name": "new_class_hash", 247 | "type": "core::starknet::class_hash::ClassHash" 248 | } 249 | ], 250 | "outputs": [], 251 | "state_mutability": "external" 252 | } 253 | ] 254 | }, 255 | { 256 | "type": "event", 257 | "name": "dojo::contract::upgradeable::upgradeable::Upgraded", 258 | "kind": "struct", 259 | "members": [ 260 | { 261 | "name": "class_hash", 262 | "type": "core::starknet::class_hash::ClassHash", 263 | "kind": "data" 264 | } 265 | ] 266 | }, 267 | { 268 | "type": "event", 269 | "name": "dojo::contract::upgradeable::upgradeable::Event", 270 | "kind": "enum", 271 | "variants": [ 272 | { 273 | "name": "Upgraded", 274 | "type": "dojo::contract::upgradeable::upgradeable::Upgraded", 275 | "kind": "nested" 276 | } 277 | ] 278 | }, 279 | { 280 | "type": "event", 281 | "name": "bytebeasts::systems::bag::bag_system::Event", 282 | "kind": "enum", 283 | "variants": [ 284 | { 285 | "name": "UpgradeableEvent", 286 | "type": "dojo::contract::upgradeable::upgradeable::Event", 287 | "kind": "nested" 288 | } 289 | ] 290 | } 291 | ] -------------------------------------------------------------------------------- /manifests/dev/deployment/abis/contracts/bytebeasts-bag_system-7ad8a155.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "impl", 4 | "name": "ContractImpl", 5 | "interface_name": "dojo::contract::contract::IContract" 6 | }, 7 | { 8 | "type": "struct", 9 | "name": "core::byte_array::ByteArray", 10 | "members": [ 11 | { 12 | "name": "data", 13 | "type": "core::array::Array::" 14 | }, 15 | { 16 | "name": "pending_word", 17 | "type": "core::felt252" 18 | }, 19 | { 20 | "name": "pending_word_len", 21 | "type": "core::integer::u32" 22 | } 23 | ] 24 | }, 25 | { 26 | "type": "interface", 27 | "name": "dojo::contract::contract::IContract", 28 | "items": [ 29 | { 30 | "type": "function", 31 | "name": "contract_name", 32 | "inputs": [], 33 | "outputs": [ 34 | { 35 | "type": "core::byte_array::ByteArray" 36 | } 37 | ], 38 | "state_mutability": "view" 39 | }, 40 | { 41 | "type": "function", 42 | "name": "namespace", 43 | "inputs": [], 44 | "outputs": [ 45 | { 46 | "type": "core::byte_array::ByteArray" 47 | } 48 | ], 49 | "state_mutability": "view" 50 | }, 51 | { 52 | "type": "function", 53 | "name": "tag", 54 | "inputs": [], 55 | "outputs": [ 56 | { 57 | "type": "core::byte_array::ByteArray" 58 | } 59 | ], 60 | "state_mutability": "view" 61 | }, 62 | { 63 | "type": "function", 64 | "name": "name_hash", 65 | "inputs": [], 66 | "outputs": [ 67 | { 68 | "type": "core::felt252" 69 | } 70 | ], 71 | "state_mutability": "view" 72 | }, 73 | { 74 | "type": "function", 75 | "name": "namespace_hash", 76 | "inputs": [], 77 | "outputs": [ 78 | { 79 | "type": "core::felt252" 80 | } 81 | ], 82 | "state_mutability": "view" 83 | }, 84 | { 85 | "type": "function", 86 | "name": "selector", 87 | "inputs": [], 88 | "outputs": [ 89 | { 90 | "type": "core::felt252" 91 | } 92 | ], 93 | "state_mutability": "view" 94 | } 95 | ] 96 | }, 97 | { 98 | "type": "impl", 99 | "name": "WorldProviderImpl", 100 | "interface_name": "dojo::world::world_contract::IWorldProvider" 101 | }, 102 | { 103 | "type": "struct", 104 | "name": "dojo::world::world_contract::IWorldDispatcher", 105 | "members": [ 106 | { 107 | "name": "contract_address", 108 | "type": "core::starknet::contract_address::ContractAddress" 109 | } 110 | ] 111 | }, 112 | { 113 | "type": "interface", 114 | "name": "dojo::world::world_contract::IWorldProvider", 115 | "items": [ 116 | { 117 | "type": "function", 118 | "name": "world", 119 | "inputs": [], 120 | "outputs": [ 121 | { 122 | "type": "dojo::world::world_contract::IWorldDispatcher" 123 | } 124 | ], 125 | "state_mutability": "view" 126 | } 127 | ] 128 | }, 129 | { 130 | "type": "impl", 131 | "name": "BagActionImpl", 132 | "interface_name": "bytebeasts::systems::bag::IBagAction" 133 | }, 134 | { 135 | "type": "struct", 136 | "name": "bytebeasts::models::potion::Potion", 137 | "members": [ 138 | { 139 | "name": "potion_id", 140 | "type": "core::integer::u32" 141 | }, 142 | { 143 | "name": "potion_name", 144 | "type": "core::felt252" 145 | }, 146 | { 147 | "name": "potion_effect", 148 | "type": "core::integer::u32" 149 | } 150 | ] 151 | }, 152 | { 153 | "type": "interface", 154 | "name": "bytebeasts::systems::bag::IBagAction", 155 | "items": [ 156 | { 157 | "type": "function", 158 | "name": "init_bag", 159 | "inputs": [ 160 | { 161 | "name": "bag_id", 162 | "type": "core::integer::u32" 163 | }, 164 | { 165 | "name": "player_id", 166 | "type": "core::integer::u32" 167 | } 168 | ], 169 | "outputs": [], 170 | "state_mutability": "external" 171 | }, 172 | { 173 | "type": "function", 174 | "name": "add_item", 175 | "inputs": [ 176 | { 177 | "name": "player_id", 178 | "type": "core::integer::u32" 179 | }, 180 | { 181 | "name": "bag_id", 182 | "type": "core::integer::u32" 183 | }, 184 | { 185 | "name": "potion", 186 | "type": "bytebeasts::models::potion::Potion" 187 | } 188 | ], 189 | "outputs": [], 190 | "state_mutability": "external" 191 | }, 192 | { 193 | "type": "function", 194 | "name": "take_out_item", 195 | "inputs": [ 196 | { 197 | "name": "player_id", 198 | "type": "core::integer::u32" 199 | }, 200 | { 201 | "name": "bag_id", 202 | "type": "core::integer::u32" 203 | } 204 | ], 205 | "outputs": [ 206 | { 207 | "type": "bytebeasts::models::potion::Potion" 208 | } 209 | ], 210 | "state_mutability": "external" 211 | } 212 | ] 213 | }, 214 | { 215 | "type": "impl", 216 | "name": "IDojoInitImpl", 217 | "interface_name": "bytebeasts::systems::bag::bag_system::IDojoInit" 218 | }, 219 | { 220 | "type": "interface", 221 | "name": "bytebeasts::systems::bag::bag_system::IDojoInit", 222 | "items": [ 223 | { 224 | "type": "function", 225 | "name": "dojo_init", 226 | "inputs": [], 227 | "outputs": [], 228 | "state_mutability": "view" 229 | } 230 | ] 231 | }, 232 | { 233 | "type": "impl", 234 | "name": "UpgradableImpl", 235 | "interface_name": "dojo::contract::upgradeable::IUpgradeable" 236 | }, 237 | { 238 | "type": "interface", 239 | "name": "dojo::contract::upgradeable::IUpgradeable", 240 | "items": [ 241 | { 242 | "type": "function", 243 | "name": "upgrade", 244 | "inputs": [ 245 | { 246 | "name": "new_class_hash", 247 | "type": "core::starknet::class_hash::ClassHash" 248 | } 249 | ], 250 | "outputs": [], 251 | "state_mutability": "external" 252 | } 253 | ] 254 | }, 255 | { 256 | "type": "event", 257 | "name": "dojo::contract::upgradeable::upgradeable::Upgraded", 258 | "kind": "struct", 259 | "members": [ 260 | { 261 | "name": "class_hash", 262 | "type": "core::starknet::class_hash::ClassHash", 263 | "kind": "data" 264 | } 265 | ] 266 | }, 267 | { 268 | "type": "event", 269 | "name": "dojo::contract::upgradeable::upgradeable::Event", 270 | "kind": "enum", 271 | "variants": [ 272 | { 273 | "name": "Upgraded", 274 | "type": "dojo::contract::upgradeable::upgradeable::Upgraded", 275 | "kind": "nested" 276 | } 277 | ] 278 | }, 279 | { 280 | "type": "event", 281 | "name": "bytebeasts::systems::bag::bag_system::Event", 282 | "kind": "enum", 283 | "variants": [ 284 | { 285 | "name": "UpgradeableEvent", 286 | "type": "dojo::contract::upgradeable::upgradeable::Event", 287 | "kind": "nested" 288 | } 289 | ] 290 | } 291 | ] -------------------------------------------------------------------------------- /manifests/dev/base/abis/contracts/bytebeasts-actions-648ac931.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "impl", 4 | "name": "ContractImpl", 5 | "interface_name": "dojo::contract::contract::IContract" 6 | }, 7 | { 8 | "type": "struct", 9 | "name": "core::byte_array::ByteArray", 10 | "members": [ 11 | { 12 | "name": "data", 13 | "type": "core::array::Array::" 14 | }, 15 | { 16 | "name": "pending_word", 17 | "type": "core::felt252" 18 | }, 19 | { 20 | "name": "pending_word_len", 21 | "type": "core::integer::u32" 22 | } 23 | ] 24 | }, 25 | { 26 | "type": "interface", 27 | "name": "dojo::contract::contract::IContract", 28 | "items": [ 29 | { 30 | "type": "function", 31 | "name": "contract_name", 32 | "inputs": [], 33 | "outputs": [ 34 | { 35 | "type": "core::byte_array::ByteArray" 36 | } 37 | ], 38 | "state_mutability": "view" 39 | }, 40 | { 41 | "type": "function", 42 | "name": "namespace", 43 | "inputs": [], 44 | "outputs": [ 45 | { 46 | "type": "core::byte_array::ByteArray" 47 | } 48 | ], 49 | "state_mutability": "view" 50 | }, 51 | { 52 | "type": "function", 53 | "name": "tag", 54 | "inputs": [], 55 | "outputs": [ 56 | { 57 | "type": "core::byte_array::ByteArray" 58 | } 59 | ], 60 | "state_mutability": "view" 61 | }, 62 | { 63 | "type": "function", 64 | "name": "name_hash", 65 | "inputs": [], 66 | "outputs": [ 67 | { 68 | "type": "core::felt252" 69 | } 70 | ], 71 | "state_mutability": "view" 72 | }, 73 | { 74 | "type": "function", 75 | "name": "namespace_hash", 76 | "inputs": [], 77 | "outputs": [ 78 | { 79 | "type": "core::felt252" 80 | } 81 | ], 82 | "state_mutability": "view" 83 | }, 84 | { 85 | "type": "function", 86 | "name": "selector", 87 | "inputs": [], 88 | "outputs": [ 89 | { 90 | "type": "core::felt252" 91 | } 92 | ], 93 | "state_mutability": "view" 94 | } 95 | ] 96 | }, 97 | { 98 | "type": "impl", 99 | "name": "WorldProviderImpl", 100 | "interface_name": "dojo::world::world_contract::IWorldProvider" 101 | }, 102 | { 103 | "type": "struct", 104 | "name": "dojo::world::world_contract::IWorldDispatcher", 105 | "members": [ 106 | { 107 | "name": "contract_address", 108 | "type": "core::starknet::contract_address::ContractAddress" 109 | } 110 | ] 111 | }, 112 | { 113 | "type": "interface", 114 | "name": "dojo::world::world_contract::IWorldProvider", 115 | "items": [ 116 | { 117 | "type": "function", 118 | "name": "world", 119 | "inputs": [], 120 | "outputs": [ 121 | { 122 | "type": "dojo::world::world_contract::IWorldDispatcher" 123 | } 124 | ], 125 | "state_mutability": "view" 126 | } 127 | ] 128 | }, 129 | { 130 | "type": "impl", 131 | "name": "ActionsImpl", 132 | "interface_name": "bytebeasts::systems::realms::IActions" 133 | }, 134 | { 135 | "type": "enum", 136 | "name": "bytebeasts::models::game::GameStatus", 137 | "variants": [ 138 | { 139 | "name": "Pending", 140 | "type": "()" 141 | }, 142 | { 143 | "name": "InProgress", 144 | "type": "()" 145 | }, 146 | { 147 | "name": "Finished", 148 | "type": "()" 149 | } 150 | ] 151 | }, 152 | { 153 | "type": "enum", 154 | "name": "core::bool", 155 | "variants": [ 156 | { 157 | "name": "False", 158 | "type": "()" 159 | }, 160 | { 161 | "name": "True", 162 | "type": "()" 163 | } 164 | ] 165 | }, 166 | { 167 | "type": "struct", 168 | "name": "bytebeasts::models::game::Game", 169 | "members": [ 170 | { 171 | "name": "game_id", 172 | "type": "core::integer::u128" 173 | }, 174 | { 175 | "name": "player_1", 176 | "type": "core::starknet::contract_address::ContractAddress" 177 | }, 178 | { 179 | "name": "player_2", 180 | "type": "core::starknet::contract_address::ContractAddress" 181 | }, 182 | { 183 | "name": "player_3", 184 | "type": "core::starknet::contract_address::ContractAddress" 185 | }, 186 | { 187 | "name": "player_4", 188 | "type": "core::starknet::contract_address::ContractAddress" 189 | }, 190 | { 191 | "name": "status", 192 | "type": "bytebeasts::models::game::GameStatus" 193 | }, 194 | { 195 | "name": "is_private", 196 | "type": "core::bool" 197 | } 198 | ] 199 | }, 200 | { 201 | "type": "interface", 202 | "name": "bytebeasts::systems::realms::IActions", 203 | "items": [ 204 | { 205 | "type": "function", 206 | "name": "create_initial_game_id", 207 | "inputs": [], 208 | "outputs": [], 209 | "state_mutability": "external" 210 | }, 211 | { 212 | "type": "function", 213 | "name": "create_game", 214 | "inputs": [], 215 | "outputs": [ 216 | { 217 | "type": "bytebeasts::models::game::Game" 218 | } 219 | ], 220 | "state_mutability": "external" 221 | }, 222 | { 223 | "type": "function", 224 | "name": "join_game", 225 | "inputs": [ 226 | { 227 | "name": "game_id", 228 | "type": "core::integer::u128" 229 | }, 230 | { 231 | "name": "player_2_address", 232 | "type": "core::starknet::contract_address::ContractAddress" 233 | } 234 | ], 235 | "outputs": [], 236 | "state_mutability": "external" 237 | } 238 | ] 239 | }, 240 | { 241 | "type": "impl", 242 | "name": "IDojoInitImpl", 243 | "interface_name": "bytebeasts::systems::realms::actions::IDojoInit" 244 | }, 245 | { 246 | "type": "interface", 247 | "name": "bytebeasts::systems::realms::actions::IDojoInit", 248 | "items": [ 249 | { 250 | "type": "function", 251 | "name": "dojo_init", 252 | "inputs": [], 253 | "outputs": [], 254 | "state_mutability": "view" 255 | } 256 | ] 257 | }, 258 | { 259 | "type": "impl", 260 | "name": "UpgradableImpl", 261 | "interface_name": "dojo::contract::upgradeable::IUpgradeable" 262 | }, 263 | { 264 | "type": "interface", 265 | "name": "dojo::contract::upgradeable::IUpgradeable", 266 | "items": [ 267 | { 268 | "type": "function", 269 | "name": "upgrade", 270 | "inputs": [ 271 | { 272 | "name": "new_class_hash", 273 | "type": "core::starknet::class_hash::ClassHash" 274 | } 275 | ], 276 | "outputs": [], 277 | "state_mutability": "external" 278 | } 279 | ] 280 | }, 281 | { 282 | "type": "event", 283 | "name": "dojo::contract::upgradeable::upgradeable::Upgraded", 284 | "kind": "struct", 285 | "members": [ 286 | { 287 | "name": "class_hash", 288 | "type": "core::starknet::class_hash::ClassHash", 289 | "kind": "data" 290 | } 291 | ] 292 | }, 293 | { 294 | "type": "event", 295 | "name": "dojo::contract::upgradeable::upgradeable::Event", 296 | "kind": "enum", 297 | "variants": [ 298 | { 299 | "name": "Upgraded", 300 | "type": "dojo::contract::upgradeable::upgradeable::Upgraded", 301 | "kind": "nested" 302 | } 303 | ] 304 | }, 305 | { 306 | "type": "event", 307 | "name": "bytebeasts::systems::realms::actions::Event", 308 | "kind": "enum", 309 | "variants": [ 310 | { 311 | "name": "UpgradeableEvent", 312 | "type": "dojo::contract::upgradeable::upgradeable::Event", 313 | "kind": "nested" 314 | } 315 | ] 316 | } 317 | ] -------------------------------------------------------------------------------- /manifests/dev/deployment/abis/contracts/bytebeasts-actions-648ac931.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "impl", 4 | "name": "ContractImpl", 5 | "interface_name": "dojo::contract::contract::IContract" 6 | }, 7 | { 8 | "type": "struct", 9 | "name": "core::byte_array::ByteArray", 10 | "members": [ 11 | { 12 | "name": "data", 13 | "type": "core::array::Array::" 14 | }, 15 | { 16 | "name": "pending_word", 17 | "type": "core::felt252" 18 | }, 19 | { 20 | "name": "pending_word_len", 21 | "type": "core::integer::u32" 22 | } 23 | ] 24 | }, 25 | { 26 | "type": "interface", 27 | "name": "dojo::contract::contract::IContract", 28 | "items": [ 29 | { 30 | "type": "function", 31 | "name": "contract_name", 32 | "inputs": [], 33 | "outputs": [ 34 | { 35 | "type": "core::byte_array::ByteArray" 36 | } 37 | ], 38 | "state_mutability": "view" 39 | }, 40 | { 41 | "type": "function", 42 | "name": "namespace", 43 | "inputs": [], 44 | "outputs": [ 45 | { 46 | "type": "core::byte_array::ByteArray" 47 | } 48 | ], 49 | "state_mutability": "view" 50 | }, 51 | { 52 | "type": "function", 53 | "name": "tag", 54 | "inputs": [], 55 | "outputs": [ 56 | { 57 | "type": "core::byte_array::ByteArray" 58 | } 59 | ], 60 | "state_mutability": "view" 61 | }, 62 | { 63 | "type": "function", 64 | "name": "name_hash", 65 | "inputs": [], 66 | "outputs": [ 67 | { 68 | "type": "core::felt252" 69 | } 70 | ], 71 | "state_mutability": "view" 72 | }, 73 | { 74 | "type": "function", 75 | "name": "namespace_hash", 76 | "inputs": [], 77 | "outputs": [ 78 | { 79 | "type": "core::felt252" 80 | } 81 | ], 82 | "state_mutability": "view" 83 | }, 84 | { 85 | "type": "function", 86 | "name": "selector", 87 | "inputs": [], 88 | "outputs": [ 89 | { 90 | "type": "core::felt252" 91 | } 92 | ], 93 | "state_mutability": "view" 94 | } 95 | ] 96 | }, 97 | { 98 | "type": "impl", 99 | "name": "WorldProviderImpl", 100 | "interface_name": "dojo::world::world_contract::IWorldProvider" 101 | }, 102 | { 103 | "type": "struct", 104 | "name": "dojo::world::world_contract::IWorldDispatcher", 105 | "members": [ 106 | { 107 | "name": "contract_address", 108 | "type": "core::starknet::contract_address::ContractAddress" 109 | } 110 | ] 111 | }, 112 | { 113 | "type": "interface", 114 | "name": "dojo::world::world_contract::IWorldProvider", 115 | "items": [ 116 | { 117 | "type": "function", 118 | "name": "world", 119 | "inputs": [], 120 | "outputs": [ 121 | { 122 | "type": "dojo::world::world_contract::IWorldDispatcher" 123 | } 124 | ], 125 | "state_mutability": "view" 126 | } 127 | ] 128 | }, 129 | { 130 | "type": "impl", 131 | "name": "ActionsImpl", 132 | "interface_name": "bytebeasts::systems::realms::IActions" 133 | }, 134 | { 135 | "type": "enum", 136 | "name": "bytebeasts::models::game::GameStatus", 137 | "variants": [ 138 | { 139 | "name": "Pending", 140 | "type": "()" 141 | }, 142 | { 143 | "name": "InProgress", 144 | "type": "()" 145 | }, 146 | { 147 | "name": "Finished", 148 | "type": "()" 149 | } 150 | ] 151 | }, 152 | { 153 | "type": "enum", 154 | "name": "core::bool", 155 | "variants": [ 156 | { 157 | "name": "False", 158 | "type": "()" 159 | }, 160 | { 161 | "name": "True", 162 | "type": "()" 163 | } 164 | ] 165 | }, 166 | { 167 | "type": "struct", 168 | "name": "bytebeasts::models::game::Game", 169 | "members": [ 170 | { 171 | "name": "game_id", 172 | "type": "core::integer::u128" 173 | }, 174 | { 175 | "name": "player_1", 176 | "type": "core::starknet::contract_address::ContractAddress" 177 | }, 178 | { 179 | "name": "player_2", 180 | "type": "core::starknet::contract_address::ContractAddress" 181 | }, 182 | { 183 | "name": "player_3", 184 | "type": "core::starknet::contract_address::ContractAddress" 185 | }, 186 | { 187 | "name": "player_4", 188 | "type": "core::starknet::contract_address::ContractAddress" 189 | }, 190 | { 191 | "name": "status", 192 | "type": "bytebeasts::models::game::GameStatus" 193 | }, 194 | { 195 | "name": "is_private", 196 | "type": "core::bool" 197 | } 198 | ] 199 | }, 200 | { 201 | "type": "interface", 202 | "name": "bytebeasts::systems::realms::IActions", 203 | "items": [ 204 | { 205 | "type": "function", 206 | "name": "create_initial_game_id", 207 | "inputs": [], 208 | "outputs": [], 209 | "state_mutability": "external" 210 | }, 211 | { 212 | "type": "function", 213 | "name": "create_game", 214 | "inputs": [], 215 | "outputs": [ 216 | { 217 | "type": "bytebeasts::models::game::Game" 218 | } 219 | ], 220 | "state_mutability": "external" 221 | }, 222 | { 223 | "type": "function", 224 | "name": "join_game", 225 | "inputs": [ 226 | { 227 | "name": "game_id", 228 | "type": "core::integer::u128" 229 | }, 230 | { 231 | "name": "player_2_address", 232 | "type": "core::starknet::contract_address::ContractAddress" 233 | } 234 | ], 235 | "outputs": [], 236 | "state_mutability": "external" 237 | } 238 | ] 239 | }, 240 | { 241 | "type": "impl", 242 | "name": "IDojoInitImpl", 243 | "interface_name": "bytebeasts::systems::realms::actions::IDojoInit" 244 | }, 245 | { 246 | "type": "interface", 247 | "name": "bytebeasts::systems::realms::actions::IDojoInit", 248 | "items": [ 249 | { 250 | "type": "function", 251 | "name": "dojo_init", 252 | "inputs": [], 253 | "outputs": [], 254 | "state_mutability": "view" 255 | } 256 | ] 257 | }, 258 | { 259 | "type": "impl", 260 | "name": "UpgradableImpl", 261 | "interface_name": "dojo::contract::upgradeable::IUpgradeable" 262 | }, 263 | { 264 | "type": "interface", 265 | "name": "dojo::contract::upgradeable::IUpgradeable", 266 | "items": [ 267 | { 268 | "type": "function", 269 | "name": "upgrade", 270 | "inputs": [ 271 | { 272 | "name": "new_class_hash", 273 | "type": "core::starknet::class_hash::ClassHash" 274 | } 275 | ], 276 | "outputs": [], 277 | "state_mutability": "external" 278 | } 279 | ] 280 | }, 281 | { 282 | "type": "event", 283 | "name": "dojo::contract::upgradeable::upgradeable::Upgraded", 284 | "kind": "struct", 285 | "members": [ 286 | { 287 | "name": "class_hash", 288 | "type": "core::starknet::class_hash::ClassHash", 289 | "kind": "data" 290 | } 291 | ] 292 | }, 293 | { 294 | "type": "event", 295 | "name": "dojo::contract::upgradeable::upgradeable::Event", 296 | "kind": "enum", 297 | "variants": [ 298 | { 299 | "name": "Upgraded", 300 | "type": "dojo::contract::upgradeable::upgradeable::Upgraded", 301 | "kind": "nested" 302 | } 303 | ] 304 | }, 305 | { 306 | "type": "event", 307 | "name": "bytebeasts::systems::realms::actions::Event", 308 | "kind": "enum", 309 | "variants": [ 310 | { 311 | "name": "UpgradeableEvent", 312 | "type": "dojo::contract::upgradeable::upgradeable::Event", 313 | "kind": "nested" 314 | } 315 | ] 316 | } 317 | ] -------------------------------------------------------------------------------- /src/models/leaderboard.cairo: -------------------------------------------------------------------------------- 1 | use starknet::ContractAddress; 2 | use core::{ 3 | result::Result, 4 | option::OptionTrait, 5 | array::ArrayTrait 6 | }; 7 | use alexandria_data_structures::array_ext::ArrayTraitExt; 8 | use alexandria_sorting::bubble_sort::bubble_sort_elements; 9 | 10 | 11 | #[derive(Copy, Drop, Serde)] 12 | #[dojo::model] 13 | pub struct LeaderboardEntry { 14 | #[key] 15 | pub player_id: u32, // player ID 16 | pub player_name: felt252, // Display name 17 | pub score: u32, // Overall score 18 | pub wins: u32, // Total wins 19 | pub losses: u32, // Total losses 20 | pub highest_score: u32, // Highest score in a single game 21 | pub is_active: bool, // Whether the player is currently active 22 | } 23 | 24 | //trait for sorting by score 25 | impl LeaderboardEntryPartialOrd of PartialOrd { 26 | fn le(lhs: LeaderboardEntry, rhs: LeaderboardEntry) -> bool { 27 | lhs.score <= rhs.score 28 | } 29 | 30 | fn ge(lhs: LeaderboardEntry, rhs: LeaderboardEntry) -> bool { 31 | lhs.score >= rhs.score 32 | } 33 | 34 | fn lt(lhs: LeaderboardEntry, rhs: LeaderboardEntry) -> bool { 35 | lhs.score < rhs.score 36 | } 37 | 38 | fn gt(lhs: LeaderboardEntry, rhs: LeaderboardEntry) -> bool { 39 | lhs.score > rhs.score 40 | } 41 | } 42 | 43 | //trait for search by player_id 44 | impl LeaderboardEntryPartialEq of PartialEq { 45 | fn eq(lhs: @LeaderboardEntry, rhs: @LeaderboardEntry) -> bool { 46 | lhs.player_id == rhs.player_id 47 | } 48 | 49 | fn ne(lhs: @LeaderboardEntry, rhs: @LeaderboardEntry) -> bool { 50 | lhs.player_id != rhs.player_id 51 | } 52 | } 53 | 54 | 55 | #[derive(Drop, Serde)] 56 | #[dojo::model] 57 | pub struct Leaderboard { 58 | #[key] 59 | pub leaderboard_id: u64, // Unique ID for leaderboard (could be incremental) 60 | pub name: felt252, // Leaderboard name (e.g., "Global", "Monthly") 61 | pub description: felt252, // Description of what this leaderboard tracks 62 | pub entries: Array, // List of leaderboard entries 63 | pub last_updated: u64, // Timestamp of last update 64 | } 65 | 66 | 67 | #[generate_trait] 68 | impl LeaderboardImpl of LeaderboardTrait { 69 | // PRIVATE METHODS 70 | 71 | fn pop_front_n(ref self: Leaderboard, mut n: usize) -> Array { 72 | // pops n elements from the front of the array, and returns them 73 | // Alexandria implementation of pop_front_n does not return the popped elements 74 | // in the current version of the library 75 | let mut res: Array = array![]; 76 | 77 | while (n != 0) { 78 | match self.entries.pop_front() { 79 | Option::Some(e) => { 80 | res.append(e); 81 | n -= 1; 82 | }, 83 | Option::None => { break; }, 84 | }; 85 | }; 86 | 87 | res 88 | } 89 | 90 | fn unsafe_add_entry(ref self: Leaderboard, entry: LeaderboardEntry) -> Result<(), felt252> { 91 | // adds user entry to leaderboard without sorting 92 | let res = self.entries.index_of(entry); 93 | if res.is_some() { 94 | return Result::Err('Entry already exists'); 95 | } 96 | self.entries.append(entry); 97 | self.last_updated = starknet::get_block_timestamp(); 98 | Result::Ok(()) 99 | } 100 | 101 | 102 | // PUBLIC METHODS 103 | 104 | fn get_leaderboard_length(ref self: Leaderboard) -> u32 { 105 | // returns number of entries in the leaderboard 106 | self.entries.len() 107 | } 108 | 109 | 110 | fn calculate_score (ref self: Leaderboard, wins: u32, highest_score: u32, losses: u32) -> u32 { 111 | // calculates score based on wins, losses and highest score 112 | wins * 100 + highest_score - losses * 70 113 | } 114 | 115 | 116 | fn upgrade_entry_stats(ref self: Leaderboard, player_id: u32, new_wins: u32, new_losses: u32, new_highest_score: u32) -> Result<(), felt252> { 117 | // recalculates score and updates entry in the leaderboard 118 | // addning new wins, losses and changing highest score to an old entry 119 | match self.get_index_by_player_id(player_id) { 120 | Result::Ok(index) => { 121 | let entry = self.entries.at(index); 122 | let total_wins: u32 = *entry.wins + new_wins; 123 | let total_losses: u32 = *entry.losses + new_losses; 124 | let highest_score: u32 = if new_highest_score > *entry.highest_score { new_highest_score } else { *entry.highest_score }; 125 | match self.update_entry( LeaderboardEntry { 126 | score: self.calculate_score(total_wins, highest_score, total_losses), 127 | wins: total_wins, 128 | losses: total_losses, 129 | highest_score: highest_score, 130 | ..*entry 131 | }) { 132 | Result::Ok(_) => Result::Ok(()), 133 | Result::Err(e) => Result::Err(e), 134 | } 135 | }, 136 | Result::Err(e) => Result::Err(e), 137 | } 138 | } 139 | 140 | fn get_index_by_player_id(ref self: Leaderboard, player_id: u32) -> Result { 141 | // returns index of entry with given player_id. Index stands for rank in the leaderboard 142 | // player with highest score has index 0 143 | let entry = LeaderboardEntry { 144 | player_id: player_id, 145 | player_name: '', 146 | score: 0, 147 | wins: 0, 148 | losses: 0, 149 | highest_score: 0, 150 | is_active: false, 151 | }; 152 | match self.entries.index_of(entry) { 153 | Option::Some(index) => Result::Ok(index), 154 | Option::None => Result::Err('Entry not found'), 155 | } 156 | } 157 | 158 | 159 | fn add_entry(ref self: Leaderboard, entry: LeaderboardEntry) -> Result<(), felt252> { 160 | // adds user entry to leaderboard and sorts internal Array 161 | let res = self.entries.index_of(entry); 162 | if res.is_some() { 163 | return Result::Err('Entry already exists'); 164 | } 165 | self.entries.append(entry); 166 | self.entries = bubble_sort_elements(self.entries, false); 167 | self.last_updated = starknet::get_block_timestamp(); 168 | Result::Ok(()) 169 | } 170 | 171 | fn add_batch(ref self: Leaderboard, mut entries: Array) -> Array { 172 | // adds multiple entries, sorts it and returns array of entries that were not added 173 | let mut not_added: Array = array![]; 174 | let mut res = entries.pop_front(); 175 | while (res.is_some()) { 176 | let entry = res.unwrap(); 177 | match self.unsafe_add_entry(entry) { 178 | Result::Err(_) => { not_added.append(entry); }, 179 | Result::Ok(_) => {}, 180 | }; 181 | res = entries.pop_front(); 182 | }; 183 | self.entries = bubble_sort_elements(self.entries, false); 184 | not_added 185 | } 186 | 187 | fn remove_entry(ref self: Leaderboard, entry: LeaderboardEntry) -> Result<(), felt252> { 188 | // removes user entry from leaderboard 189 | match self.entries.index_of(entry) { 190 | Option::Some(index) => { 191 | let mut left = self.pop_front_n(index); 192 | let _ = self.entries.pop_front(); 193 | left.append_all(ref self.entries); 194 | self.entries = left; 195 | self.last_updated = starknet::get_block_timestamp(); 196 | Result::Ok(()) 197 | }, 198 | Option::None => Result::Err('Entry not found'), 199 | } 200 | } 201 | 202 | fn update_entry(ref self: Leaderboard, entry: LeaderboardEntry) -> Result<(), felt252> { 203 | // updates user entry in leaderboard, sorts array 204 | match self.remove_entry(entry) { 205 | Result::Ok(_) => { 206 | match self.add_entry(entry) { 207 | Result::Ok(_) => Result::Ok(()), 208 | Result::Err(e) => Result::Err(e) 209 | } 210 | }, 211 | Result::Err(e) => Result::Err(e), 212 | } 213 | } 214 | 215 | 216 | fn get_entries(ref self: Leaderboard) -> Array { 217 | // returns all entries in the leaderboard 218 | self.entries.clone() 219 | } 220 | 221 | fn get_slice(ref self: Leaderboard, start: u32, end: u32) -> Result, felt252> { 222 | // returns entries from start to end (exclusive) 223 | // can be used to get top of the leaderboard 224 | let mut res: Array = array![]; 225 | match self.entries.len() { 226 | 0 => Result::Err('Leaderboard is empty'), 227 | _ => { 228 | if (start >= end) { 229 | return Result::Err('Invalid range'); 230 | } 231 | if (end > self.entries.len()) { 232 | return Result::Err('End index out of bounds'); 233 | } 234 | let mut i = start; 235 | while (i < end) { 236 | res.append(self.entries.at(i).clone()); 237 | i += 1; 238 | }; 239 | Result::Ok(res) 240 | }, 241 | } 242 | } 243 | 244 | } 245 | -------------------------------------------------------------------------------- /manifests/dev/base/abis/contracts/bytebeasts-tournament_system-1f2bbf20.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "impl", 4 | "name": "ContractImpl", 5 | "interface_name": "dojo::contract::contract::IContract" 6 | }, 7 | { 8 | "type": "struct", 9 | "name": "core::byte_array::ByteArray", 10 | "members": [ 11 | { 12 | "name": "data", 13 | "type": "core::array::Array::" 14 | }, 15 | { 16 | "name": "pending_word", 17 | "type": "core::felt252" 18 | }, 19 | { 20 | "name": "pending_word_len", 21 | "type": "core::integer::u32" 22 | } 23 | ] 24 | }, 25 | { 26 | "type": "interface", 27 | "name": "dojo::contract::contract::IContract", 28 | "items": [ 29 | { 30 | "type": "function", 31 | "name": "contract_name", 32 | "inputs": [], 33 | "outputs": [ 34 | { 35 | "type": "core::byte_array::ByteArray" 36 | } 37 | ], 38 | "state_mutability": "view" 39 | }, 40 | { 41 | "type": "function", 42 | "name": "namespace", 43 | "inputs": [], 44 | "outputs": [ 45 | { 46 | "type": "core::byte_array::ByteArray" 47 | } 48 | ], 49 | "state_mutability": "view" 50 | }, 51 | { 52 | "type": "function", 53 | "name": "tag", 54 | "inputs": [], 55 | "outputs": [ 56 | { 57 | "type": "core::byte_array::ByteArray" 58 | } 59 | ], 60 | "state_mutability": "view" 61 | }, 62 | { 63 | "type": "function", 64 | "name": "name_hash", 65 | "inputs": [], 66 | "outputs": [ 67 | { 68 | "type": "core::felt252" 69 | } 70 | ], 71 | "state_mutability": "view" 72 | }, 73 | { 74 | "type": "function", 75 | "name": "namespace_hash", 76 | "inputs": [], 77 | "outputs": [ 78 | { 79 | "type": "core::felt252" 80 | } 81 | ], 82 | "state_mutability": "view" 83 | }, 84 | { 85 | "type": "function", 86 | "name": "selector", 87 | "inputs": [], 88 | "outputs": [ 89 | { 90 | "type": "core::felt252" 91 | } 92 | ], 93 | "state_mutability": "view" 94 | } 95 | ] 96 | }, 97 | { 98 | "type": "impl", 99 | "name": "WorldProviderImpl", 100 | "interface_name": "dojo::world::world_contract::IWorldProvider" 101 | }, 102 | { 103 | "type": "struct", 104 | "name": "dojo::world::world_contract::IWorldDispatcher", 105 | "members": [ 106 | { 107 | "name": "contract_address", 108 | "type": "core::starknet::contract_address::ContractAddress" 109 | } 110 | ] 111 | }, 112 | { 113 | "type": "interface", 114 | "name": "dojo::world::world_contract::IWorldProvider", 115 | "items": [ 116 | { 117 | "type": "function", 118 | "name": "world", 119 | "inputs": [], 120 | "outputs": [ 121 | { 122 | "type": "dojo::world::world_contract::IWorldDispatcher" 123 | } 124 | ], 125 | "state_mutability": "view" 126 | } 127 | ] 128 | }, 129 | { 130 | "type": "impl", 131 | "name": "TournamentActionImpl", 132 | "interface_name": "bytebeasts::systems::tournament::ITournamentAction" 133 | }, 134 | { 135 | "type": "enum", 136 | "name": "bytebeasts::models::tournament::TournamentStatus", 137 | "variants": [ 138 | { 139 | "name": "Pending", 140 | "type": "()" 141 | }, 142 | { 143 | "name": "Ongoing", 144 | "type": "()" 145 | }, 146 | { 147 | "name": "Completed", 148 | "type": "()" 149 | } 150 | ] 151 | }, 152 | { 153 | "type": "struct", 154 | "name": "bytebeasts::models::tournament::Tournament", 155 | "members": [ 156 | { 157 | "name": "tournament_id", 158 | "type": "core::integer::u32" 159 | }, 160 | { 161 | "name": "name", 162 | "type": "core::felt252" 163 | }, 164 | { 165 | "name": "status", 166 | "type": "bytebeasts::models::tournament::TournamentStatus" 167 | }, 168 | { 169 | "name": "entry_fee", 170 | "type": "core::integer::u32" 171 | }, 172 | { 173 | "name": "max_participants", 174 | "type": "core::integer::u32" 175 | }, 176 | { 177 | "name": "current_participants", 178 | "type": "core::array::Array::" 179 | }, 180 | { 181 | "name": "prize_pool", 182 | "type": "core::integer::u32" 183 | } 184 | ] 185 | }, 186 | { 187 | "type": "interface", 188 | "name": "bytebeasts::systems::tournament::ITournamentAction", 189 | "items": [ 190 | { 191 | "type": "function", 192 | "name": "create_tournament", 193 | "inputs": [ 194 | { 195 | "name": "tournament_id", 196 | "type": "core::integer::u32" 197 | }, 198 | { 199 | "name": "name", 200 | "type": "core::felt252" 201 | }, 202 | { 203 | "name": "status", 204 | "type": "bytebeasts::models::tournament::TournamentStatus" 205 | }, 206 | { 207 | "name": "entry_fee", 208 | "type": "core::integer::u32" 209 | }, 210 | { 211 | "name": "max_participants", 212 | "type": "core::integer::u32" 213 | }, 214 | { 215 | "name": "current_participants", 216 | "type": "core::array::Array::" 217 | }, 218 | { 219 | "name": "prize_pool", 220 | "type": "core::integer::u32" 221 | } 222 | ], 223 | "outputs": [], 224 | "state_mutability": "external" 225 | }, 226 | { 227 | "type": "function", 228 | "name": "register_player", 229 | "inputs": [ 230 | { 231 | "name": "tournament_id", 232 | "type": "core::integer::u32" 233 | }, 234 | { 235 | "name": "new_player_id", 236 | "type": "core::integer::u32" 237 | } 238 | ], 239 | "outputs": [], 240 | "state_mutability": "external" 241 | }, 242 | { 243 | "type": "function", 244 | "name": "start_tournament", 245 | "inputs": [ 246 | { 247 | "name": "tournament_id", 248 | "type": "core::integer::u32" 249 | } 250 | ], 251 | "outputs": [], 252 | "state_mutability": "external" 253 | }, 254 | { 255 | "type": "function", 256 | "name": "complete_tournament", 257 | "inputs": [ 258 | { 259 | "name": "tournament_id", 260 | "type": "core::integer::u32" 261 | }, 262 | { 263 | "name": "player_id", 264 | "type": "core::integer::u32" 265 | } 266 | ], 267 | "outputs": [], 268 | "state_mutability": "external" 269 | }, 270 | { 271 | "type": "function", 272 | "name": "get_tournament", 273 | "inputs": [ 274 | { 275 | "name": "tournament_id", 276 | "type": "core::integer::u32" 277 | } 278 | ], 279 | "outputs": [ 280 | { 281 | "type": "bytebeasts::models::tournament::Tournament" 282 | } 283 | ], 284 | "state_mutability": "view" 285 | } 286 | ] 287 | }, 288 | { 289 | "type": "impl", 290 | "name": "IDojoInitImpl", 291 | "interface_name": "bytebeasts::systems::tournament::tournament_system::IDojoInit" 292 | }, 293 | { 294 | "type": "interface", 295 | "name": "bytebeasts::systems::tournament::tournament_system::IDojoInit", 296 | "items": [ 297 | { 298 | "type": "function", 299 | "name": "dojo_init", 300 | "inputs": [], 301 | "outputs": [], 302 | "state_mutability": "view" 303 | } 304 | ] 305 | }, 306 | { 307 | "type": "impl", 308 | "name": "UpgradableImpl", 309 | "interface_name": "dojo::contract::upgradeable::IUpgradeable" 310 | }, 311 | { 312 | "type": "interface", 313 | "name": "dojo::contract::upgradeable::IUpgradeable", 314 | "items": [ 315 | { 316 | "type": "function", 317 | "name": "upgrade", 318 | "inputs": [ 319 | { 320 | "name": "new_class_hash", 321 | "type": "core::starknet::class_hash::ClassHash" 322 | } 323 | ], 324 | "outputs": [], 325 | "state_mutability": "external" 326 | } 327 | ] 328 | }, 329 | { 330 | "type": "event", 331 | "name": "dojo::contract::upgradeable::upgradeable::Upgraded", 332 | "kind": "struct", 333 | "members": [ 334 | { 335 | "name": "class_hash", 336 | "type": "core::starknet::class_hash::ClassHash", 337 | "kind": "data" 338 | } 339 | ] 340 | }, 341 | { 342 | "type": "event", 343 | "name": "dojo::contract::upgradeable::upgradeable::Event", 344 | "kind": "enum", 345 | "variants": [ 346 | { 347 | "name": "Upgraded", 348 | "type": "dojo::contract::upgradeable::upgradeable::Upgraded", 349 | "kind": "nested" 350 | } 351 | ] 352 | }, 353 | { 354 | "type": "event", 355 | "name": "bytebeasts::systems::tournament::tournament_system::Event", 356 | "kind": "enum", 357 | "variants": [ 358 | { 359 | "name": "UpgradeableEvent", 360 | "type": "dojo::contract::upgradeable::upgradeable::Event", 361 | "kind": "nested" 362 | } 363 | ] 364 | } 365 | ] --------------------------------------------------------------------------------