From b31c3733652fc705ef8faa34d9024edb5a69d281 Mon Sep 17 00:00:00 2001 From: gianmarcoalarcon Date: Wed, 18 Oct 2023 14:03:21 +0700 Subject: [PATCH 1/4] Update hello-dojo tutorial --- src/cairo/hello-dojo.md | 176 ++++++++++++++++++++------------- src/toolchain/torii/graphql.md | 2 +- 2 files changed, 106 insertions(+), 72 deletions(-) diff --git a/src/cairo/hello-dojo.md b/src/cairo/hello-dojo.md index 9791bf57..058d5d86 100644 --- a/src/cairo/hello-dojo.md +++ b/src/cairo/hello-dojo.md @@ -20,9 +20,7 @@ Inspect the contents of the `dojo-starter` project, and you'll notice the follow ```bash src - systems - - raw_contract.cairo - - with_decorator.cairo + - actions.cairo - lib.cairo - models.cairo - utils.cairo @@ -66,28 +64,25 @@ Our `Moves` model houses a `player` field. At the same tine, we have the `#[key] In a similar vein, we have a `Position` component that have a Vec2 data structure. Vec holds `x` and `y` values. Once again, this component is indexed by the `player` field. -Now, let's examine the `src/systems/raw_contract.cairo` file: +Now, let's examine the `src/actions.cairo` file: ```rust,ignore -#[starknet::contract] -mod player_actions_external { +// dojo decorator +#[dojo::contract] +mod actions { use starknet::{ContractAddress, get_caller_address}; - use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; use dojo_examples::models::{Position, Moves, Direction, Vec2}; use dojo_examples::utils::next_position; - use super::IPlayerActions; - - #[storage] - struct Storage { - world_dispatcher: IWorldDispatcher, - } + use super::IActions; + // declaring custom event struct #[event] #[derive(Drop, starknet::Event)] enum Event { Moved: Moved, } + // declaring custom event struct #[derive(Drop, starknet::Event)] struct Moved { player: ContractAddress, @@ -96,30 +91,62 @@ mod player_actions_external { // impl: implement functions specified in trait #[external(v0)] - impl PlayerActionsImpl of IPlayerActions { + impl ActionsImpl of IActions { + // ContractState is defined by system decorator expansion fn spawn(self: @ContractState) { + // Access the world dispatcher for reading. let world = self.world_dispatcher.read(); + + // Get the address of the current caller, possibly the player's address. let player = get_caller_address(); + + // Retrieve the player's current position from the world. let position = get!(world, player, (Position)); + + // Retrieve the player's move data, e.g., how many moves they have left. + let moves = get!(world, player, (Moves)); + + // Update the world state with the new data. + // 1. Increase the player's remaining moves by 10. + // 2. Move the player's position 10 units in both the x and y direction. set!( world, ( - Moves { player, remaining: 10, last_direction: Direction::None(()) }, - Position { player, vec: Vec2 { x: 10, y: 10 } }, + Moves { + player, remaining: moves.remaining + 10, last_direction: Direction::None(()) + }, + Position { + player, vec: Vec2 { x: position.vec.x + 10, y: position.vec.y + 10 } + }, ) ); } + // Implementation of the move function for the ContractState struct. fn move(self: @ContractState, direction: Direction) { + // Access the world dispatcher for reading. let world = self.world_dispatcher.read(); + + // Get the address of the current caller, possibly the player's address. let player = get_caller_address(); + + // Retrieve the player's current position and moves data from the world. let (mut position, mut moves) = get!(world, player, (Position, Moves)); + + // Deduct one from the player's remaining moves. moves.remaining -= 1; + + // Update the last direction the player moved in. moves.last_direction = direction; + + // Calculate the player's next position based on the provided direction. let next = next_position(position, direction); + + // Update the world state with the new moves data and position. set!(world, (moves, next)); + + // Emit an event to the world to notify about the player's move. emit!(world, Moved { player, direction }); - return (); } } } @@ -129,22 +156,33 @@ mod player_actions_external { #### System is a contract -As you can see a `System` is like a regular Starknet contract. It imports the Models we defined earlier and exposes two functions `spawn` and `move`. These functions are called when a player spawns into the world and when they move respectively. +As you can see a `System` is like a dojo(starknet) contract. It imports the Models we defined earlier and exposes two functions `spawn` and `move`. These functions are called when a player spawns into the world and when they move respectively. ```rust,ignore +// Retrieve the player's current position from the world. let position = get!(world, player, (Position)); + +// Retrieve the player's move data, e.g., how many moves they have left. +let moves = get!(world, player, (Moves)); ``` -Here we use `get!` [command](./commands.md) to retrieve the `Position` model for the `player` entity, which is the address of the caller. +Here we use `get!` [command](./commands.md) to retrieve the `Position` and `Moves` model for the `player` entity, which is the address of the caller. Now the next line: ```rust,ignore +// Update the world state with the new data. +// 1. Increase the player's remaining moves by 10. +// 2. Move the player's position 10 units in both the x and y direction. set!( world, ( - Moves { player, remaining: 10, last_direction: Direction::None(()) }, - Position { player, vec: Vec2 { x: 10, y: 10 } }, + Moves { + player, remaining: moves.remaining + 10, last_direction: Direction::None(()) + }, + Position { + player, vec: Vec2 { x: position.vec.x + 10, y: position.vec.y + 10} + }, ) ); ``` @@ -191,40 +229,44 @@ World name: test [1] 🌎 Building World state.... > No remote World found [2] 🧰 Evaluating Worlds diff.... - > Total diffs found: 6 + > Total diffs found: 5 [3] 📦 Preparing for migration.... - > Total items to be migrated (6): New 6 Update 0 + > Total items to be migrated (5): New 5 Update 0 # Executor > Contract address: 0x5c3494b21bc92d40abdc40cdc54af66f22fb92bf876665d982c765a2cc0e06a # Base Contract > Class Hash: 0x7aec2b7d7064c1294a339cd90060331ff704ab573e4ee9a1b699be2215c11c9 # World - > Contract address: 0x71b95a2c000545624c51813444b57dbcdcc153dfc79b6b0e3a9a536168d1e16 + > Contract address: 0x1af130f7b9027f3748c1e3b10ca4a82ac836a30ac4f2f84025e83a99a922a0c # Models (2) Moves > Class hash: 0xb37482a660983dfbf65968caa26eab260d3e1077986454b52ac06e58ae20c4 Position > Class hash: 0x6ffc643cbc4b2fb9c424242b18175a5e142269b45f4463d1cd4dddb7a2e5095 - > Registered at: 0x36eedf55545c4e770da905325bb00f853864a15d1fbf4fbfb54f668f074d553 -# Contracts (2) -player_actions - > Contract address: 0x2e4ff2961ac4f49e1e3c2b55c5090cc80ca61c38fdcabc7acabbf81e28a4abe -player_actions_external - > Contract address: 0x7cb0ac6dd2cd2a38bd27ce47ba429a1f31bf69055040342253f972e0b0473ce + > Registered at: 0x3e74b09d320ceb5d4401842bec805489019c04202bc23bc67a385f6e537dce0 +# Contracts (1) +actions + > Contract address: 0x69a474a39b11d05c07bb9090fd1961b8e1c87aa5643e7b97087cb0c7620356a -🎉 Successfully migrated World at address 0x71b95a2c000545624c51813444b57dbcdcc153dfc79b6b0e3a9a536168d1e16 +🎉 Successfully migrated World at address 0x1af130f7b9027f3748c1e3b10ca4a82ac836a30ac4f2f84025e83a99a922a0c ✨ Updating manifest.json... ✨ Done. + ``` Your 🌎 is now deployed at `0x71b95a2c000545624c51813444b57dbcdcc153dfc79b6b0e3a9a536168d1e16`! This establishes the world address for your project. -Let's discuss the `Scarb.toml` file in the project. This file contains environment variables that make running CLI commands in your project a breeze. (Read more about it [here](./config.md)). Make sure your file specifies the version of Dojo you have installed! +Let's discuss the `Scarb.toml` file in the project. This file contains environment variables that make running CLI commands in your project a breeze. (Read more about it [here](./config.md)). Make sure your file specifies the version of Dojo you have installed!. In this case version `v0.3.0` + +```toml +[dependencies] +dojo = { git = "https://github.com/dojoengine/dojo", rev = "v0.3.0" } +``` ### Indexing @@ -237,24 +279,23 @@ torii --world 0x71b95a2c000545624c51813444b57dbcdcc153dfc79b6b0e3a9a536168d1e16 Running the command mentioned above starts a Torii server on your local machine. This server uses SQLite as its database and is accessible at http://0.0.0.0:8080/graphql. Torii will automatically organize your data into tables, making it easy for you to perform queries using GraphQL. When you run the command, you'll see terminal output that looks something like this: ```bash -2023-10-13T10:14:10.903554Z INFO torii::server: 🚀 Torii listening at http://0.0.0.0:8080 -2023-10-13T10:14:10.903568Z INFO torii::server: Graphql playground: http://0.0.0.0:8080/graphql - -2023-10-13T10:14:10.904767Z INFO torii_core::engine: processed block: 0 -2023-10-13T10:14:10.905334Z INFO torii_core::engine: processed block: 1 -2023-10-13T10:14:10.905949Z INFO torii_core::engine: processed block: 2 -2023-10-13T10:14:10.906422Z INFO torii_core::engine: processed block: 3 -2023-10-13T10:14:10.907088Z INFO torii_core::engine: processed block: 4 -2023-10-13T10:14:10.907951Z INFO torii_core::engine: processed block: 5 -2023-10-13T10:14:10.908566Z INFO torii_core::engine: processed block: 6 -2023-10-13T10:14:10.909239Z INFO torii_core::engine: processed block: 7 -2023-10-13T10:14:10.920225Z INFO torii_core::processors::register_model: Registered model: Moves -2023-10-13T10:14:10.928852Z INFO torii_core::processors::register_model: Registered model: Position -2023-10-13T10:14:10.929576Z INFO torii_core::engine: processed block: 8 -2023-10-13T10:14:10.930337Z INFO torii_core::engine: processed block: 9 -2023-10-13T10:14:10.930982Z INFO torii_core::engine: processed block: 10 -2023-10-13T10:14:10.931467Z INFO torii_core::engine: processed block: 11 -2023-10-13T10:14:10.931964Z INFO torii_core::engine: processed block: 12 +2023-10-18T06:49:48.184233Z INFO torii::server: 🚀 Torii listening at http://0.0.0.0:8080 +2023-10-18T06:49:48.184244Z INFO torii::server: Graphql playground: http://0.0.0.0:8080/graphql + +2023-10-18T06:49:48.185648Z INFO torii_core::engine: processed block: 0 +2023-10-18T06:49:48.186129Z INFO torii_core::engine: processed block: 1 +2023-10-18T06:49:48.186720Z INFO torii_core::engine: processed block: 2 +2023-10-18T06:49:48.187202Z INFO torii_core::engine: processed block: 3 +2023-10-18T06:49:48.187674Z INFO torii_core::engine: processed block: 4 +2023-10-18T06:49:48.188215Z INFO torii_core::engine: processed block: 5 +2023-10-18T06:49:48.188611Z INFO torii_core::engine: processed block: 6 +2023-10-18T06:49:48.188985Z INFO torii_core::engine: processed block: 7 +2023-10-18T06:49:48.199592Z INFO torii_core::processors::register_model: Registered model: Moves +2023-10-18T06:49:48.210032Z INFO torii_core::processors::register_model: Registered model: Position +2023-10-18T06:49:48.210571Z INFO torii_core::engine: processed block: 8 +2023-10-18T06:49:48.211678Z INFO torii_core::engine: processed block: 9 +2023-10-18T06:49:48.212335Z INFO torii_core::engine: processed block: 10 + ``` You can observe that our `Moves` and `Position` models have been successfully registered. @@ -282,7 +323,7 @@ After you run the query, you will receive an output like this: "name": "Moves", "class_hash": "0xb37482a660983dfbf65968caa26eab260d3e1077986454b52ac06e58ae20c4", "transaction_hash": "", - "created_at": "2023-10-13 14:55:47" + "created_at": "2023-10-18 06:49:48" } } } @@ -308,22 +349,15 @@ Once you execute the subscription, you will receive notifications whenever new e To accomplish this, we have to go back to our primary terminal and check the contracts section. ```bash -# Contracts (2) -player_actions - > Contract address: 0x2e4ff2961ac4f49e1e3c2b55c5090cc80ca61c38fdcabc7acabbf81e28a4abe -player_actions_external - > Contract address: 0x7cb0ac6dd2cd2a38bd27ce47ba429a1f31bf69055040342253f972e0b0473ce +# Contracts (1) +actions + > Contract address: 0x69a474a39b11d05c07bb9090fd1961b8e1c87aa5643e7b97087cb0c7620356a ``` -We have `player_actions` contract address and `player_actions_external` contract address. -Since these two contracts have the same functionality, we can choose any of them to start to create entities. - -For this example let's choose player_actions contract address: `0x2e4ff2961ac4f49e1e3c2b55c5090cc80ca61c38fdcabc7acabbf81e28a4abe` - -In your main local terminal, run the following command: +We have to use `actions` contract address to start to create entities. In your main local terminal, run the following command: ```bash -sozo execute 0x2e4ff2961ac4f49e1e3c2b55c5090cc80ca61c38fdcabc7acabbf81e28a4abe spawn +sozo execute 0x69a474a39b11d05c07bb9090fd1961b8e1c87aa5643e7b97087cb0c7620356a spawn ``` By running this command, you've activated the spawn system, resulting in the creation of a new entity. This action establishes a local world that you can interact with. @@ -339,11 +373,11 @@ Now, go back to your GraphiQL IDE, and you will notice that you have received th "0x517ececd29116499f4a1b64b094da79ba08dfd54a3edaa316134c41f8160973" ], "model_names": "Moves", - "event_id": "0x000000000000000000000000000000000000000000000000000000000000000d:0x0000:0x0000", - "created_at": "2023-10-13 15:08:53", - "updated_at": "2023-10-13 15:08:53" + "event_id": "0x000000000000000000000000000000000000000000000000000000000000000b:0x0000:0x0000", + "created_at": "2023-10-18 06:53:12", + "updated_at": "2023-10-18 06:53:12" } - } + } } -------------------------------------------------------------------------------------------------------- { @@ -354,11 +388,11 @@ Now, go back to your GraphiQL IDE, and you will notice that you have received th "0x517ececd29116499f4a1b64b094da79ba08dfd54a3edaa316134c41f8160973" ], "model_names": "Moves,Position", - "event_id": "0x000000000000000000000000000000000000000000000000000000000000000d:0x0000:0x0001", - "created_at": "2023-10-13 15:08:53", - "updated_at": "2023-10-13 15:08:53" + "event_id": "0x000000000000000000000000000000000000000000000000000000000000000b:0x0000:0x0001", + "created_at": "2023-10-18 06:53:12", + "updated_at": "2023-10-18 06:53:12" } - } + } } ``` diff --git a/src/toolchain/torii/graphql.md b/src/toolchain/torii/graphql.md index dbc0b4d0..b1bbf875 100644 --- a/src/toolchain/torii/graphql.md +++ b/src/toolchain/torii/graphql.md @@ -111,7 +111,7 @@ subscription modelRegistered { Graphql also supports subscription to a targeted entity or model, for this we have to pass its id as an argument -In this example, our serve provides a `entityUpdated` subscription, which should notify clients whenever an entity with id `0x28cd7ee02d7f6ec9810e75b930e8e607793b302445abbdee0ac88143f18da20` is updated. On the same subscription we can get the model(components) values of entityUpdated. A client can execute a subscription that looks like this: +In this example, our server provides a `entityUpdated` subscription, which should notify clients whenever an entity with id `0x28cd7ee02d7f6ec9810e75b930e8e607793b302445abbdee0ac88143f18da20` is updated. On the same subscription we can get the model(components) values of the updated entity . A client can execute a subscription that looks like this: ```graphql subscription { From 37941fc32510b95c318bc79fea9c45f96bedb4be Mon Sep 17 00:00:00 2001 From: gianmarcoalarcon Date: Wed, 18 Oct 2023 14:22:13 +0700 Subject: [PATCH 2/4] Fix identation --- src/cairo/hello-dojo.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cairo/hello-dojo.md b/src/cairo/hello-dojo.md index 058d5d86..e7529fbe 100644 --- a/src/cairo/hello-dojo.md +++ b/src/cairo/hello-dojo.md @@ -178,11 +178,11 @@ set!( world, ( Moves { - player, remaining: moves.remaining + 10, last_direction: Direction::None(()) - }, + player, remaining: moves.remaining + 10, last_direction: Direction::None(()) + }, Position { - player, vec: Vec2 { x: position.vec.x + 10, y: position.vec.y + 10} - }, + player, vec: Vec2 { x: position.vec.x + 10, y: position.vec.y + 10} + }, ) ); ``` From 37e2392cedb26834fc2819d6b4f20b66059034f4 Mon Sep 17 00:00:00 2001 From: gianmarcoalarcon Date: Wed, 18 Oct 2023 14:24:51 +0700 Subject: [PATCH 3/4] Fix identation --- src/cairo/hello-dojo.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cairo/hello-dojo.md b/src/cairo/hello-dojo.md index e7529fbe..2a88200e 100644 --- a/src/cairo/hello-dojo.md +++ b/src/cairo/hello-dojo.md @@ -377,7 +377,7 @@ Now, go back to your GraphiQL IDE, and you will notice that you have received th "created_at": "2023-10-18 06:53:12", "updated_at": "2023-10-18 06:53:12" } - } + } } -------------------------------------------------------------------------------------------------------- { @@ -392,7 +392,7 @@ Now, go back to your GraphiQL IDE, and you will notice that you have received th "created_at": "2023-10-18 06:53:12", "updated_at": "2023-10-18 06:53:12" } - } + } } ``` From cff5984928bd224c14e3f6e141ef405ee70c2cb7 Mon Sep 17 00:00:00 2001 From: gianmarcoalarcon Date: Wed, 18 Oct 2023 15:28:12 +0700 Subject: [PATCH 4/4] Remove componets file --- src/SUMMARY.md | 2 -- src/cairo/components.md | 1 - 2 files changed, 3 deletions(-) delete mode 100644 src/cairo/components.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 5d9d6d98..1cbbc513 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -31,8 +31,6 @@ - [0.2.0 -> 0.3.0](./cairo/migration/0.3.0.md) - [ECS in 15 minutes](./cairo/hello-dojo.md) - - [Components](./cairo/components.md) - - [Entities](./cairo/entities.md) - [Testing](./cairo/testing.md) diff --git a/src/cairo/components.md b/src/cairo/components.md deleted file mode 100644 index 0eac4eb5..00000000 --- a/src/cairo/components.md +++ /dev/null @@ -1 +0,0 @@ -# Components