From 946b627ab36c9e3a3bdb0daa9780d672e56cc17f Mon Sep 17 00:00:00 2001 From: "remy.baranx@gmail.com" Date: Sun, 7 Jul 2024 17:38:54 +0200 Subject: [PATCH] Handle get()/set() get_field_name()/set_field_name() functions --- crates/dojo-core/src/base_test.cairo | 2 +- crates/dojo-core/src/lib.cairo | 2 + crates/dojo-core/src/model.cairo | 31 +- crates/dojo-core/src/model_test.cairo | 198 + crates/dojo-core/src/resource_metadata.cairo | 65 +- crates/dojo-core/src/utils.cairo | 50 + crates/dojo-core/src/world.cairo | 327 +- crates/dojo-core/src/world_test.cairo | 170 +- crates/dojo-lang/src/inline_macros/delete.rs | 9 +- crates/dojo-lang/src/inline_macros/get.rs | 4 +- crates/dojo-lang/src/inline_macros/set.rs | 8 +- crates/dojo-lang/src/introspect/layout.rs | 2 +- .../manifests/dev/base/abis/dojo-world.json | 69 +- .../manifests/dev/base/dojo-world.toml | 4 +- crates/dojo-lang/src/model.rs | 495 +- crates/dojo-lang/src/plugin_test_data/model | 7551 +++++++++++++++-- crates/dojo-lang/src/semantics/test_data/get | 22 +- crates/dojo-lang/src/semantics/test_data/set | 92 +- crates/dojo-world/src/contracts/abi/world.rs | 69 +- crates/dojo-world/src/contracts/model.rs | 9 +- crates/dojo-world/src/contracts/naming.rs | 4 +- crates/sozo/ops/src/events.rs | 2 +- crates/torii/types-test/src/contracts.cairo | 2 +- examples/spawn-and-move/Scarb.toml | 22 +- .../dojo_examples-actions-40b6994c.json | 24 + .../manifests/dev/base/abis/dojo-world.json | 69 +- .../dojo_examples-actions-40b6994c.toml | 4 +- .../dojo_examples-mock_token-31599eb2.toml | 4 +- .../manifests/dev/base/dojo-world.toml | 4 +- .../dojo_examples-actions-40b6994c.json | 36 + .../dev/deployment/abis/dojo-world.json | 69 +- ...examples-DirectionsAvailable-22b3dd08.json | 433 + .../manifests/dev/deployment/manifest.json | 364 +- .../manifests/dev/deployment/manifest.toml | 36 +- .../dojo_examples-actions-40b6994c.json | 24 + .../release/base/abis/dojo-world.json | 69 +- .../dojo_examples-actions-40b6994c.toml | 4 +- .../dojo_examples-mock_token-31599eb2.toml | 4 +- .../manifests/release/base/dojo-world.toml | 4 +- examples/spawn-and-move/src/actions.cairo | 62 +- examples/spawn-and-move/src/mock_token.cairo | 1 - 41 files changed, 9381 insertions(+), 1039 deletions(-) create mode 100644 crates/dojo-core/src/model_test.cairo create mode 100644 examples/spawn-and-move/manifests/dev/deployment/abis/models/dojo_examples-DirectionsAvailable-22b3dd08.json diff --git a/crates/dojo-core/src/base_test.cairo b/crates/dojo-core/src/base_test.cairo index 40b6414822..e2cad0d9f0 100644 --- a/crates/dojo-core/src/base_test.cairo +++ b/crates/dojo-core/src/base_test.cairo @@ -178,7 +178,7 @@ mod invalid_model { fn selector(self: @ContractState) -> felt252 { // NOTE: Need to update this value if address changes // Pre-computed address of a contract deployed through the world. - 0x21b19f95ff0f382a069dc7034f95584b300133665ee506789c76ba729e42b66 + 0x25a125a2629cdf446548e060301ef7a870ff49e035b776b0092db6637910160 } fn namespace(self: @ContractState) -> ByteArray { diff --git a/crates/dojo-core/src/lib.cairo b/crates/dojo-core/src/lib.cairo index 2aed7f15fe..627cf21739 100644 --- a/crates/dojo-core/src/lib.cairo +++ b/crates/dojo-core/src/lib.cairo @@ -7,6 +7,8 @@ mod database; mod database_test; mod interfaces; mod model; +#[cfg(test)] +mod model_test; mod contract; mod packing; #[cfg(test)] diff --git a/crates/dojo-core/src/model.cairo b/crates/dojo-core/src/model.cairo index d26d43f54a..3ebbd5e0bc 100644 --- a/crates/dojo-core/src/model.cairo +++ b/crates/dojo-core/src/model.cairo @@ -1,10 +1,32 @@ -use dojo::world::IWorldDispatcher; +use dojo::world::{IWorldDispatcher, ModelIndex}; use starknet::SyscallResult; +/// Trait that is implemented at Cairo level for each struct that is a model. +trait ModelEntity { + fn id(self: @T) -> felt252; + fn values(self: @T) -> Span; + fn from_values(entity_id: felt252, values: Span) -> T; + fn get(world: IWorldDispatcher, entity_id: felt252) -> T; + fn update(self: @T, world: IWorldDispatcher); + fn delete(self: @T, world: IWorldDispatcher); + fn get_member( + world: IWorldDispatcher, entity_id: felt252, member_id: felt252, + ) -> Span; + fn set_member(self: @T, world: IWorldDispatcher, member_id: felt252, values: Span,); +} + trait Model { - fn entity( - world: IWorldDispatcher, keys: Span, layout: dojo::database::introspect::Layout - ) -> T; + fn get(world: IWorldDispatcher, keys: Span) -> T; + // Note: `get` is implemented with a generated trait because it takes + // the list of model keys as separated parameters. + fn set(self: @T, world: IWorldDispatcher); + fn delete(self: @T, world: IWorldDispatcher); + + fn get_member( + world: IWorldDispatcher, keys: Span, member_id: felt252, + ) -> Span; + + fn set_member(self: @T, world: IWorldDispatcher, member_id: felt252, values: Span,); /// Returns the name of the model as it was written in Cairo code. fn name() -> ByteArray; @@ -25,6 +47,7 @@ trait Model { fn name_hash() -> felt252; fn namespace_hash() -> felt252; + fn entity_id(self: @T) -> felt252; fn keys(self: @T) -> Span; fn values(self: @T) -> Span; fn layout() -> dojo::database::introspect::Layout; diff --git a/crates/dojo-core/src/model_test.cairo b/crates/dojo-core/src/model_test.cairo new file mode 100644 index 0000000000..68a17d604d --- /dev/null +++ b/crates/dojo-core/src/model_test.cairo @@ -0,0 +1,198 @@ +use dojo::test_utils::{spawn_test_world}; +use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; + +// Utils +fn deploy_world() -> IWorldDispatcher { + spawn_test_world("dojo", array![]) +} + +#[derive(Copy, Drop, Serde)] +#[dojo::model] +struct Foo { + #[key] + k1: u8, + #[key] + k2: felt252, + v1: u128, + v2: u32 +} + +#[test] +fn test_id() { + let mvalues = FooEntity { __id: 1, v1: 3, v2: 4 }; + assert!(mvalues.id() == 1); +} + +#[test] +fn test_values() { + let mvalues = FooEntity { __id: 1, v1: 3, v2: 4 }; + let expected_values = array![3, 4].span(); + + let values = dojo::model::ModelEntity::::values(@mvalues); + assert!(expected_values == values); +} + +#[test] +fn test_from_values() { + let values = array![3, 4].span(); + + let model_entity = dojo::model::ModelEntity::::from_values(1, values); + assert!(model_entity.__id == 1 && model_entity.v1 == 3 && model_entity.v2 == 4); +} + +#[test] +#[should_panic(expected: "ModelEntity `FooEntity`: deserialization failed.")] +fn test_from_values_bad_data() { + let values = array![3].span(); + let _ = dojo::model::ModelEntity::::from_values(1, values); +} + +#[test] +fn test_get_and_update_entity() { + let world = deploy_world(); + world.register_model(foo::TEST_CLASS_HASH.try_into().unwrap()); + + let foo = Foo { k1: 1, k2: 2, v1: 3, v2: 4 }; + foo.set(world); + + let entity_id = foo.entity_id(); + let mut entity = FooEntityTrait::get(world, entity_id); + assert!(entity.__id == entity_id && entity.v1 == entity.v1 && entity.v2 == entity.v2); + + entity.v1 = 12; + entity.v2 = 18; + + entity.update(world); + + let read_values = FooEntityTrait::get(world, entity_id); + assert!(read_values.v1 == entity.v1 && read_values.v2 == entity.v2); +} + +#[test] +fn test_delete_entity() { + let world = deploy_world(); + world.register_model(foo::TEST_CLASS_HASH.try_into().unwrap()); + + let foo = Foo { k1: 1, k2: 2, v1: 3, v2: 4 }; + foo.set(world); + + let entity_id = foo.entity_id(); + let mut entity = FooEntityTrait::get(world, entity_id); + entity.delete(world); + + let read_values = FooEntityTrait::get(world, entity_id); + assert!(read_values.v1 == 0 && read_values.v2 == 0); +} + +#[test] +fn test_get_and_set_member_from_entity() { + let world = deploy_world(); + world.register_model(foo::TEST_CLASS_HASH.try_into().unwrap()); + + let foo = Foo { k1: 1, k2: 2, v1: 3, v2: 4 }; + foo.set(world); + + let v1_raw_value: Span = dojo::model::ModelEntity::< + FooEntity + >::get_member(world, foo.entity_id(), selector!("v1")); + + assert!(v1_raw_value.len() == 1); + assert!(*v1_raw_value.at(0) == 3); + + let entity = FooEntityTrait::get(world, foo.entity_id()); + entity.set_member(world, selector!("v1"), array![42].span()); + + let entity = FooEntityTrait::get(world, foo.entity_id()); + assert!(entity.v1 == 42); +} + +#[test] +fn test_get_and_set_field_name() { + let world = deploy_world(); + world.register_model(foo::TEST_CLASS_HASH.try_into().unwrap()); + + let foo = Foo { k1: 1, k2: 2, v1: 3, v2: 4 }; + foo.set(world); + + let v1 = FooEntityTrait::get_v1(world, foo.entity_id()); + assert!(foo.v1 == v1); + + let entity = FooEntityTrait::get(world, foo.entity_id()); + entity.set_v1(world, 42); + + let v1 = FooEntityTrait::get_v1(world, foo.entity_id()); + assert!(v1 == 42); +} + +#[test] +fn test_get_and_set_from_model() { + let world = deploy_world(); + world.register_model(foo::TEST_CLASS_HASH.try_into().unwrap()); + + let foo = Foo { k1: 1, k2: 2, v1: 3, v2: 4 }; + foo.set(world); + + let read_entity = FooTrait::get(world, foo.k1, foo.k2); + + assert!( + foo.k1 == read_entity.k1 + && foo.k2 == read_entity.k2 + && foo.v1 == read_entity.v1 + && foo.v2 == read_entity.v2 + ); +} + +#[test] +fn test_delete_from_model() { + let world = deploy_world(); + world.register_model(foo::TEST_CLASS_HASH.try_into().unwrap()); + + let foo = Foo { k1: 1, k2: 2, v1: 3, v2: 4 }; + foo.set(world); + foo.delete(world); + + let read_entity = FooTrait::get(world, foo.k1, foo.k2); + assert!( + read_entity.k1 == foo.k1 + && read_entity.k2 == foo.k2 + && read_entity.v1 == 0 + && read_entity.v2 == 0 + ); +} + +#[test] +fn test_get_and_set_member_from_model() { + let world = deploy_world(); + world.register_model(foo::TEST_CLASS_HASH.try_into().unwrap()); + + let foo = Foo { k1: 1, k2: 2, v1: 3, v2: 4 }; + let keys = array![foo.k1.into(), foo.k2.into()].span(); + foo.set(world); + + let v1_raw_value = dojo::model::Model::::get_member(world, keys, selector!("v1")); + + assert!(v1_raw_value.len() == 1); + assert!(*v1_raw_value.at(0) == 3); + + foo.set_member(world, selector!("v1"), array![42].span()); + let foo = FooTrait::get(world, foo.k1, foo.k2); + assert!(foo.v1 == 42); +} + +#[test] +fn test_get_and_set_field_name_from_model() { + let world = deploy_world(); + world.register_model(foo::TEST_CLASS_HASH.try_into().unwrap()); + + let foo = Foo { k1: 1, k2: 2, v1: 3, v2: 4 }; + foo.set(world); + + let v1 = FooTrait::get_v1(world, foo.k1, foo.k2); + assert!(v1 == 3); + + foo.set_v1(world, 42); + + let v1 = FooTrait::get_v1(world, foo.k1, foo.k2); + assert!(v1 == 42); +} + diff --git a/crates/dojo-core/src/resource_metadata.cairo b/crates/dojo-core/src/resource_metadata.cairo index 601f05f391..dde35752e1 100644 --- a/crates/dojo-core/src/resource_metadata.cairo +++ b/crates/dojo-core/src/resource_metadata.cairo @@ -3,8 +3,9 @@ //! Manually expand to ensure that dojo-core //! does not depend on dojo plugin to be built. //! -use dojo::world::{IWorldDispatcherTrait}; +use dojo::world::{IWorldDispatcherTrait, ModelIndex}; use dojo::model::Model; +use dojo::utils; fn initial_address() -> starknet::ContractAddress { starknet::contract_address_const::<0>() @@ -24,12 +25,8 @@ struct ResourceMetadata { } impl ResourceMetadataModel of dojo::model::Model { - fn entity( - world: dojo::world::IWorldDispatcher, - keys: Span, - layout: dojo::database::introspect::Layout - ) -> ResourceMetadata { - let values = world.entity(Self::selector(), keys, layout); + fn get(world: dojo::world::IWorldDispatcher, keys: Span) -> ResourceMetadata { + let values = world.entity(Self::selector(), ModelIndex::Keys(keys), Self::layout()); let mut serialized = core::array::ArrayTrait::new(); core::array::serialize_array_helper(keys, ref serialized); core::array::serialize_array_helper(values, ref serialized); @@ -45,6 +42,51 @@ impl ResourceMetadataModel of dojo::model::Model { core::option::OptionTrait::::unwrap(entity) } + fn set(self: @ResourceMetadata, world: dojo::world::IWorldDispatcher,) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, Self::selector(), ModelIndex::Keys(self.keys()), self.values(), Self::layout() + ); + } + + fn delete(self: @ResourceMetadata, world: dojo::world::IWorldDispatcher,) { + world.delete_entity(Self::selector(), ModelIndex::Keys(self.keys()), Self::layout()); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, keys: Span, member_id: felt252 + ) -> Span { + match utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + let entity_id = utils::entity_id_from_keys(keys); + world + .entity( + Self::selector(), ModelIndex::MemberId((entity_id, member_id)), field_layout + ) + }, + Option::None => panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @ResourceMetadata, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span + ) { + match utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + world + .set_entity( + Self::selector(), + ModelIndex::MemberId((self.entity_id(), member_id)), + values, + field_layout + ) + }, + Option::None => panic_with_felt252('bad member id') + } + } + #[inline(always)] fn name() -> ByteArray { "ResourceMetadata" @@ -74,11 +116,16 @@ impl ResourceMetadataModel of dojo::model::Model { } fn name_hash() -> felt252 { - dojo::utils::hash(@Self::name()) + utils::hash(@Self::name()) } fn namespace_hash() -> felt252 { - dojo::utils::hash(@Self::namespace()) + utils::hash(@Self::namespace()) + } + + #[inline(always)] + fn entity_id(self: @ResourceMetadata) -> felt252 { + poseidon::poseidon_hash_span(self.keys()) } #[inline(always)] diff --git a/crates/dojo-core/src/utils.cairo b/crates/dojo-core/src/utils.cairo index 92654ce538..860bbe5759 100644 --- a/crates/dojo-core/src/utils.cairo +++ b/crates/dojo-core/src/utils.cairo @@ -4,3 +4,53 @@ fn hash(data: @ByteArray) -> felt252 { Serde::serialize(data, ref serialized); poseidon::poseidon_hash_span(serialized.span()) } + +/// Computes the entity id from the keys. +/// +/// # Arguments +/// +/// * `keys` - The keys of the entity. +/// +/// # Returns +/// +/// The entity id. +fn entity_id_from_keys(keys: Span) -> felt252 { + poseidon::poseidon_hash_span(keys) +} + +/// Find the layout of a model field based on its selector. +/// +/// # Arguments +/// +/// * `model_layout` - The full model layout (must be a Layout::Struct). +/// * `member_selector` - The model field selector. +/// +/// # Returns +/// Some(Layout) if the field layout has been found, None otherwise. +fn find_model_field_layout( + model_layout: dojo::database::introspect::Layout, member_selector: felt252 +) -> Option { + match model_layout { + dojo::database::introspect::Layout::Struct(struct_layout) => { + let mut i = 0; + let layout = loop { + if i >= struct_layout.len() { + break Option::None; + } + + let field_layout = *struct_layout.at(i); + if field_layout.selector == member_selector { + break Option::Some(field_layout.layout); + } + i += 1; + }; + + layout + }, + _ => { + // should never happen as model layouts are always struct layouts. + panic_with_felt252('Unexpected model layout'); + Option::None + } + } +} diff --git a/crates/dojo-core/src/world.cairo b/crates/dojo-core/src/world.cairo index 2db09d2f80..0a4b1d2017 100644 --- a/crates/dojo-core/src/world.cairo +++ b/crates/dojo-core/src/world.cairo @@ -3,6 +3,14 @@ use traits::{Into, TryInto}; use option::OptionTrait; use dojo::resource_metadata::ResourceMetadata; +#[derive(Copy, Drop, Serde, Debug, PartialEq)] +enum ModelIndex { + Keys: Span, + Id: felt252, + // (entity_id, member_id) + MemberId: (felt252, felt252) +} + #[starknet::interface] trait IWorld { fn metadata(self: @T, resource_id: felt252) -> ResourceMetadata; @@ -16,19 +24,27 @@ trait IWorld { fn upgrade_contract(ref self: T, address: ContractAddress, class_hash: ClassHash) -> ClassHash; fn uuid(ref self: T) -> usize; fn emit(self: @T, keys: Array, values: Span); + fn entity( - self: @T, model: felt252, keys: Span, layout: dojo::database::introspect::Layout + self: @T, + model_selector: felt252, + index: ModelIndex, + layout: dojo::database::introspect::Layout ) -> Span; fn set_entity( ref self: T, - model: felt252, - keys: Span, + model_selector: felt252, + index: ModelIndex, values: Span, layout: dojo::database::introspect::Layout ); fn delete_entity( - ref self: T, model: felt252, keys: Span, layout: dojo::database::introspect::Layout + ref self: T, + model_selector: felt252, + index: ModelIndex, + layout: dojo::database::introspect::Layout ); + fn base(self: @T) -> ClassHash; /// In Dojo, there are 2 levels of authorization: `owner` and `writer`. @@ -43,7 +59,7 @@ trait IWorld { fn revoke_writer(ref self: T, resource: felt252, contract: ContractAddress); fn can_write_resource(self: @T, resource_id: felt252, contract: ContractAddress) -> bool; - fn can_write_model(self: @T, model_id: felt252, contract: ContractAddress) -> bool; + fn can_write_model(self: @T, model_selector: felt252, contract: ContractAddress) -> bool; fn can_write_namespace(self: @T, namespace_id: felt252, contract: ContractAddress) -> bool; } @@ -72,6 +88,7 @@ mod Errors { const OWNER_ONLY_UPGRADE: felt252 = 'only owner can upgrade'; const OWNER_ONLY_UPDATE: felt252 = 'only owner can update'; const NAMESPACE_ALREADY_REGISTERED: felt252 = 'namespace already registered'; + const DELETE_ENTITY_MEMBER: felt252 = 'cannot delete entity member'; const UNEXPECTED_ERROR: felt252 = 'unexpected error'; } @@ -108,8 +125,9 @@ mod world { use dojo::world::{IWorldDispatcher, IWorld, IUpgradeableWorld}; use dojo::resource_metadata; use dojo::resource_metadata::ResourceMetadata; + use dojo::utils::entity_id_from_keys; - use super::Errors; + use super::{Errors, ModelIndex}; const WORLD: felt252 = 0; @@ -135,6 +153,7 @@ mod world { NamespaceRegistered: NamespaceRegistered, ModelRegistered: ModelRegistered, StoreSetRecord: StoreSetRecord, + StoreUpdateRecord: StoreUpdateRecord, StoreDelRecord: StoreDelRecord, WriterUpdated: WriterUpdated, OwnerUpdated: OwnerUpdated, @@ -202,10 +221,17 @@ mod world { values: Span, } + #[derive(Drop, starknet::Event)] + struct StoreUpdateRecord { + table: felt252, + entity_id: felt252, + values: Span, + } + #[derive(Drop, starknet::Event)] struct StoreDelRecord { table: felt252, - keys: Span, + entity_id: felt252, } #[derive(Drop, starknet::Event)] @@ -288,14 +314,15 @@ mod world { /// /// `resource_id` - The resource id. fn metadata(self: @ContractState, resource_id: felt252) -> ResourceMetadata { + let mut model = array![resource_id]; + let entity_id = entity_id_from_keys(model.span()); let mut data = self - ._read_model_data( + ._read_model_entity( dojo::model::Model::::selector(), - array![resource_id].span(), + entity_id, Model::::layout() ); - let mut model = array![resource_id]; core::array::serialize_array_helper(data, ref model); let mut model_span = model.span(); @@ -315,11 +342,11 @@ mod world { ); let model = Model::::selector(); - let keys = Model::::keys(@metadata); + let entity_id = Model::::entity_id(@metadata); let values = Model::::values(@metadata); let layout = Model::::layout(); - self._write_model_data(model, keys, values, layout); + self._write_model_entity(model, entity_id, values, layout); EventEmitter::emit( ref self, @@ -473,20 +500,20 @@ mod world { /// /// # Arguments /// - /// * `model_id` - The model selector. + /// * `model_selector` - The model selector. /// * `contract` - The name of the contract. /// /// # Returns /// /// * `bool` - True if the contract can write to the model, false otherwise fn can_write_model( - self: @ContractState, model_id: felt252, contract: ContractAddress + self: @ContractState, model_selector: felt252, contract: ContractAddress ) -> bool { // TODO: use match self.resources... directly when https://github.com/starkware-libs/cairo/pull/5743 fixed - let resource: ResourceData = self.resources.read(model_id); + let resource: ResourceData = self.resources.read(model_selector); match resource { ResourceData::Model((_, model_address)) => self - ._check_model_write_access(model_id, model_address, contract), + ._check_model_write_access(model_selector, model_address, contract), _ => panic_with_felt252(Errors::INVALID_RESOURCE_SELECTOR) } } @@ -721,73 +748,115 @@ mod world { emit_event_syscall(keys.span(), values).unwrap_syscall(); } - /// Sets the model value for an entity. + /// Gets the values of a model record/entity/member. + /// Returns a zero initialized model value if the record/entity/member has not been set. /// /// # Arguments /// - /// * `model` - The selector of the model to be set. - /// * `keys` - The key to be used to find the entity. - /// * `value_names` - The name of model fields which are not a key. - /// * `values` - The value to be set. - /// * `layout` - The memory layout of the entity. + /// * `model_selector` - The selector of the model to be retrieved. + /// * `index` - The index of the record/entity/member to read. + /// * `layout` - The memory layout of the model. + /// + /// # Returns + /// + /// * `Span` - The serialized value of the model, zero initialized if not set. + fn entity( + self: @ContractState, + model_selector: felt252, + index: ModelIndex, + layout: dojo::database::introspect::Layout + ) -> Span { + match index { + ModelIndex::Keys(keys) => { + let entity_id = entity_id_from_keys(keys); + self._read_model_entity(model_selector, entity_id, layout) + }, + ModelIndex::Id(entity_id) => { + self._read_model_entity(model_selector, entity_id, layout) + }, + ModelIndex::MemberId(( + entity_id, member_id + )) => { self._read_model_member(model_selector, entity_id, member_id, layout) } + } + } + + /// Sets the model value for a model record/entity/member. + /// + /// # Arguments + /// + /// * `model_selector` - The selector of the model to be set. + /// * `index` - The index of the record/entity/member to write. + /// * `values` - The value to be set, serialized using the model layout format. + /// * `layout` - The memory layout of the model. fn set_entity( ref self: ContractState, - model: felt252, - keys: Span, + model_selector: felt252, + index: ModelIndex, values: Span, layout: dojo::database::introspect::Layout ) { assert( - self.can_write_model(model, get_caller_address()), Errors::NO_MODEL_WRITE_ACCESS + self.can_write_model(model_selector, get_caller_address()), + Errors::NO_MODEL_WRITE_ACCESS ); - self._write_model_data(model, keys, values, layout); - EventEmitter::emit(ref self, StoreSetRecord { table: model, keys, values }); + match index { + ModelIndex::Keys(keys) => { + let entity_id = entity_id_from_keys(keys); + self._write_model_entity(model_selector, entity_id, values, layout); + EventEmitter::emit( + ref self, StoreSetRecord { table: model_selector, keys, values } + ); + }, + ModelIndex::Id(entity_id) => { + self._write_model_entity(model_selector, entity_id, values, layout); + EventEmitter::emit( + ref self, StoreUpdateRecord { table: model_selector, entity_id, values } + ); + }, + ModelIndex::MemberId(( + entity_id, member_id + )) => { + self._write_model_member(model_selector, entity_id, member_id, values, layout) + } + } } - /// Deletes a model from an entity. + /// Deletes a record/entity of a model.. /// Deleting is setting all the values to 0 in the given layout. /// /// # Arguments /// - /// * `model` - The selector of the model to be deleted. - /// * `keys` - The key to be used to find the entity. - /// * `value_names` - The name of model fields which are not a key. - /// * `layout` - The memory layout of the entity. + /// * `model_selector` - The selector of the model to be deleted. + /// * `index` - The index of the record/entity to delete. + /// * `layout` - The memory layout of the model. fn delete_entity( ref self: ContractState, - model: felt252, - keys: Span, + model_selector: felt252, + index: ModelIndex, layout: dojo::database::introspect::Layout ) { assert( - self.can_write_model(model, get_caller_address()), Errors::NO_MODEL_WRITE_ACCESS + self.can_write_model(model_selector, get_caller_address()), + Errors::NO_MODEL_WRITE_ACCESS ); - self._delete_model_data(model, keys, layout); - EventEmitter::emit(ref self, StoreDelRecord { table: model, keys }); - } - - /// Gets the model value for an entity. Returns a zero initialized - /// model value if the entity has not been set. - /// - /// # Arguments - /// - /// * `model` - The selector of the model to be retrieved. - /// * `keys` - The keys used to find the entity. - /// * `value_names` - The name of model fields which are not a key. - /// * `layout` - The memory layout of the entity. - /// - /// # Returns - /// - /// * `Span` - The serialized value of the model, zero initialized if not set. - fn entity( - self: @ContractState, - model: felt252, - keys: Span, - layout: dojo::database::introspect::Layout - ) -> Span { - self._read_model_data(model, keys, layout) + match index { + ModelIndex::Keys(keys) => { + let entity_id = entity_id_from_keys(keys); + self._delete_model_entity(model_selector, entity_id, layout); + EventEmitter::emit( + ref self, StoreDelRecord { table: model_selector, entity_id } + ); + }, + ModelIndex::Id(entity_id) => { + self._delete_model_entity(model_selector, entity_id, layout); + EventEmitter::emit( + ref self, StoreDelRecord { table: model_selector, entity_id } + ); + }, + ModelIndex::MemberId(_) => { panic_with_felt252(Errors::DELETE_ENTITY_MEMBER); } + } } /// Gets the base contract class hash. @@ -944,7 +1013,7 @@ mod world { /// - the calling account has the owner and/or writer role for the model namespace. /// /// # Arguments - /// * `model_id` - the model selector to check. + /// * `model_selector` - the model selector to check. /// * `model_address` - the model contract address. /// * `contract` - the calling contract. /// @@ -953,13 +1022,13 @@ mod world { /// fn _check_model_write_access( self: @ContractState, - model_id: felt252, + model_selector: felt252, model_address: ContractAddress, contract: ContractAddress ) -> bool { - if !self.is_writer(model_id, contract) - && !self.is_account_owner(model_id) - && !self.is_account_writer(model_id) { + if !self.is_writer(model_selector, contract) + && !self.is_account_owner(model_selector) + && !self.is_account_writer(model_selector) { let model = IModelDispatcher { contract_address: model_address }; self._check_basic_write_access(model.namespace_hash(), contract) } else { @@ -987,78 +1056,80 @@ mod world { || self.is_account_writer(resource_id) } - /// Write a new model record. + /// Write a new entity. /// /// # Arguments - /// * `model` - the model selector - /// * `keys` - the list of model keys to identify the record + /// * `model_selector` - the model selector + /// * `entity_id` - the id used to identify the record /// * `values` - the field values of the record /// * `layout` - the model layout - fn _write_model_data( + fn _write_model_entity( ref self: ContractState, - model: felt252, - keys: Span, + model_selector: felt252, + entity_id: felt252, values: Span, layout: dojo::database::introspect::Layout ) { - let model_key = poseidon::poseidon_hash_span(keys); let mut offset = 0; match layout { Layout::Fixed(layout) => { - Self::_write_fixed_layout(model, model_key, values, ref offset, layout); + Self::_write_fixed_layout( + model_selector, entity_id, values, ref offset, layout + ); }, Layout::Struct(layout) => { - Self::_write_struct_layout(model, model_key, values, ref offset, layout); + Self::_write_struct_layout( + model_selector, entity_id, values, ref offset, layout + ); }, _ => { panic!("Unexpected layout type for a model."); } }; } - /// Delete a model record. + /// Delete an entity. /// /// # Arguments - /// * `model` - the model selector - /// * `keys` - the list of model keys to identify the record + /// * `model_selector` - the model selector + /// * `entity_id` - the ID of the entity to remove. /// * `layout` - the model layout - fn _delete_model_data( + fn _delete_model_entity( ref self: ContractState, - model: felt252, - keys: Span, + model_selector: felt252, + entity_id: felt252, layout: dojo::database::introspect::Layout ) { - let model_key = poseidon::poseidon_hash_span(keys); - match layout { - Layout::Fixed(layout) => { Self::_delete_fixed_layout(model, model_key, layout); }, + Layout::Fixed(layout) => { + Self::_delete_fixed_layout(model_selector, entity_id, layout); + }, Layout::Struct(layout) => { - Self::_delete_struct_layout(model, model_key, layout); + Self::_delete_struct_layout(model_selector, entity_id, layout); }, _ => { panic!("Unexpected layout type for a model."); } }; } - /// Read a model record. + /// Read an entity. /// /// # Arguments - /// * `model` - the model selector - /// * `keys` - the list of model keys to identify the record + /// * `model_selector` - the model selector + /// * `entity_id` - the ID of the entity to read. /// * `layout` - the model layout - fn _read_model_data( + fn _read_model_entity( self: @ContractState, - model: felt252, - keys: Span, + model_selector: felt252, + entity_id: felt252, layout: dojo::database::introspect::Layout ) -> Span { - let model_key = poseidon::poseidon_hash_span(keys); let mut read_data = ArrayTrait::::new(); match layout { Layout::Fixed(layout) => { - Self::_read_fixed_layout(model, model_key, ref read_data, layout); + Self::_read_fixed_layout(model_selector, entity_id, ref read_data, layout); }, Layout::Struct(layout) => { - Self::_read_struct_layout(model, model_key, ref read_data, layout); + Self::_read_struct_layout(model_selector, entity_id, ref read_data, layout); }, _ => { panic!("Unexpected layout type for a model."); } }; @@ -1066,9 +1137,53 @@ mod world { read_data.span() } - /// Compute the full field key from parent key and current field key. - fn _field_key(parent_key: felt252, field_key: felt252) -> felt252 { - poseidon::poseidon_hash_span(array![parent_key, field_key].span()) + /// Read a model member value. + /// + /// # Arguments + /// * `model_selector` - the model selector + /// * `entity_id` - the ID of the entity for which to read a member. + /// * `member_id` - the selector of the model member to read. + /// * `layout` - the model layout + fn _read_model_member( + self: @ContractState, + model_selector: felt252, + entity_id: felt252, + member_id: felt252, + layout: dojo::database::introspect::Layout + ) -> Span { + let mut read_data = ArrayTrait::::new(); + Self::_read_layout( + model_selector, Self::_combine_key(entity_id, member_id), ref read_data, layout + ); + + read_data.span() + } + + /// Write a model member value. + /// + /// # Arguments + /// * `model_selector` - the model selector + /// * `entity_id` - the ID of the entity for which to write a member. + /// * `member_id` - the selector of the model member to write. + /// * `values` - the new member value. + /// * `layout` - the model layout + fn _write_model_member( + self: @ContractState, + model_selector: felt252, + entity_id: felt252, + member_id: felt252, + values: Span, + layout: dojo::database::introspect::Layout + ) { + let mut offset = 0; + Self::_write_layout( + model_selector, Self::_combine_key(entity_id, member_id), values, ref offset, layout + ) + } + + /// Combine parent and child keys to build one full key. + fn _combine_key(parent_key: felt252, child_key: felt252) -> felt252 { + poseidon::poseidon_hash_span(array![parent_key, child_key].span()) } /// Append some values to an array. @@ -1189,7 +1304,7 @@ mod world { if i >= array_len { break; } - let key = Self::_field_key(key, i.into()); + let key = Self::_combine_key(key, i.into()); Self::_write_layout(model, key, values, ref offset, item_layout); @@ -1247,7 +1362,7 @@ mod world { } let field_layout = *layout.at(i); - let field_key = Self::_field_key(key, field_layout.selector); + let field_key = Self::_combine_key(key, field_layout.selector); Self::_write_layout(model, field_key, values, ref offset, field_layout.layout); @@ -1277,7 +1392,7 @@ mod world { } let field_layout = *layout.at(i); - let key = Self::_field_key(key, i.into()); + let key = Self::_combine_key(key, i.into()); Self::_write_layout(model, key, values, ref offset, field_layout); @@ -1301,7 +1416,7 @@ mod world { offset += 1; // find the corresponding layout and then write the full variant - let variant_data_key = Self::_field_key(key, variant); + let variant_data_key = Self::_combine_key(key, variant); match Self::_find_variant_layout(variant, variant_layouts) { Option::Some(layout) => Self::_write_layout( @@ -1376,7 +1491,7 @@ mod world { } let field_layout = *layout.at(i); - let key = Self::_field_key(key, field_layout.selector); + let key = Self::_combine_key(key, field_layout.selector); Self::_delete_layout(model, key, field_layout.layout); @@ -1398,7 +1513,7 @@ mod world { } let field_layout = *layout.at(i); - let key = Self::_field_key(key, i.into()); + let key = Self::_combine_key(key, i.into()); Self::_delete_layout(model, key, field_layout); @@ -1418,7 +1533,7 @@ mod world { database::delete(model, key, array![251].span()); // find the corresponding layout and the delete the full variant - let variant_data_key = Self::_field_key(key, variant); + let variant_data_key = Self::_combine_key(key, variant); match Self::_find_variant_layout(variant, variant_layouts) { Option::Some(layout) => Self::_delete_layout(model, variant_data_key, layout), @@ -1496,7 +1611,7 @@ mod world { break; } - let field_key = Self::_field_key(key, i.into()); + let field_key = Self::_combine_key(key, i.into()); Self::_read_layout(model, field_key, ref read_data, item_layout); i += 1; @@ -1547,7 +1662,7 @@ mod world { } let field_layout = *layout.at(i); - let field_key = Self::_field_key(key, field_layout.selector); + let field_key = Self::_combine_key(key, field_layout.selector); Self::_read_layout(model, field_key, ref read_data, field_layout.layout); @@ -1572,7 +1687,7 @@ mod world { } let field_layout = *layout.at(i); - let field_key = Self::_field_key(key, i.into()); + let field_key = Self::_combine_key(key, i.into()); Self::_read_layout(model, field_key, ref read_data, field_layout); i += 1; @@ -1595,7 +1710,7 @@ mod world { read_data.append(variant); // find the corresponding layout and the read the variant data - let variant_data_key = Self::_field_key(key, variant); + let variant_data_key = Self::_combine_key(key, variant); match Self::_find_variant_layout(variant, variant_layouts) { Option::Some(layout) => Self::_read_layout( diff --git a/crates/dojo-core/src/world_test.cairo b/crates/dojo-core/src/world_test.cairo index 1958726cfd..ed3f4e45b9 100644 --- a/crates/dojo-core/src/world_test.cairo +++ b/crates/dojo-core/src/world_test.cairo @@ -22,6 +22,7 @@ use dojo::config::component::Config::{ }; use dojo::model::Model; use dojo::benchmarks::{Character, GasCounterImpl}; +use dojo::utils::entity_id_from_keys; #[derive(Introspect, Copy, Drop, Serde)] enum OneEnum { @@ -324,7 +325,7 @@ mod bar { .read() .delete_entity( dojo::model::Model::::selector(), - array![get_caller_address().into()].span(), + dojo::model::ModelIndex::Keys(array![get_caller_address().into()].span()), dojo::model::Model::::layout() ); } @@ -957,6 +958,20 @@ fn test_can_call_init() { dojo_init.dojo_init(); } +#[test] +fn test_set_entity_by_id() { + let world = deploy_world(); + world.register_model(foo::TEST_CLASS_HASH.try_into().unwrap()); + let selector = dojo::model::Model::::selector(); + let entity_id = entity_id_from_keys(array![0x01234].span()); + let values = create_foo(); + let layout = dojo::model::Model::::layout(); + + world.set_entity(selector, dojo::model::ModelIndex::Id(entity_id), values, layout); + let read_values = world.entity(selector, dojo::model::ModelIndex::Id(entity_id), layout); + assert_array(read_values, values); +} + #[test] fn test_set_entity_with_fixed_layout() { let world = deploy_world(); @@ -966,8 +981,8 @@ fn test_set_entity_with_fixed_layout() { let values = create_foo(); let layout = dojo::model::Model::::layout(); - world.set_entity(selector, get_key_test(), values, layout); - let read_values = world.entity(selector, keys, layout); + world.set_entity(selector, dojo::model::ModelIndex::Keys(get_key_test()), values, layout); + let read_values = world.entity(selector, dojo::model::ModelIndex::Keys(keys), layout); assert_array(read_values, values); } @@ -981,9 +996,9 @@ fn test_set_entity_with_struct_layout() { let values = create_struct_simple_model(); let layout = dojo::model::Model::::layout(); - world.set_entity(selector, keys, values, layout); + world.set_entity(selector, dojo::model::ModelIndex::Keys(keys), values, layout); - let read_values = world.entity(selector, keys, layout); + let read_values = world.entity(selector, dojo::model::ModelIndex::Keys(keys), layout); assert_array(read_values, values); } @@ -997,9 +1012,9 @@ fn test_set_entity_with_struct_tuple_layout() { let values = create_struct_with_tuple(); let layout = dojo::model::Model::::layout(); - world.set_entity(selector, keys, values, layout); + world.set_entity(selector, dojo::model::ModelIndex::Keys(keys), values, layout); - let read_values = world.entity(selector, keys, layout); + let read_values = world.entity(selector, dojo::model::ModelIndex::Keys(keys), layout); assert_array(read_values, values); } @@ -1014,16 +1029,16 @@ fn test_set_entity_with_struct_enum_layout() { let layout = dojo::model::Model::::layout(); // test with the first variant - world.set_entity(selector, keys, values, layout); + world.set_entity(selector, dojo::model::ModelIndex::Keys(keys), values, layout); - let read_values = world.entity(selector, keys, layout); + let read_values = world.entity(selector, dojo::model::ModelIndex::Keys(keys), layout); assert_array(read_values, values); // then override with the second variant let values = create_struct_with_enum_second_variant(); - world.set_entity(selector, keys, values, layout); + world.set_entity(selector, dojo::model::ModelIndex::Keys(keys), values, layout); - let read_values = world.entity(selector, keys, layout); + let read_values = world.entity(selector, dojo::model::ModelIndex::Keys(keys), layout); assert_array(read_values, values); } @@ -1037,9 +1052,9 @@ fn test_set_entity_with_struct_simple_array_layout() { let values = create_struct_simple_array_model(); let layout = dojo::model::Model::::layout(); - world.set_entity(selector, keys, values, layout); + world.set_entity(selector, dojo::model::ModelIndex::Keys(keys), values, layout); - let read_values = world.entity(selector, keys, layout); + let read_values = world.entity(selector, dojo::model::ModelIndex::Keys(keys), layout); assert_array(read_values, values); } @@ -1053,9 +1068,9 @@ fn test_set_entity_with_struct_complex_array_layout() { let values = create_struct_complex_array_model(); let layout = dojo::model::Model::::layout(); - world.set_entity(selector, keys, values, layout); + world.set_entity(selector, dojo::model::ModelIndex::Keys(keys), values, layout); - let read_values = world.entity(selector, keys, layout); + let read_values = world.entity(selector, dojo::model::ModelIndex::Keys(keys), layout); assert_array(read_values, values); } @@ -1069,9 +1084,9 @@ fn test_set_entity_with_struct_layout_and_byte_array() { let values = create_struct_byte_array_model(); let layout = dojo::model::Model::::layout(); - world.set_entity(selector, keys, values, layout); + world.set_entity(selector, dojo::model::ModelIndex::Keys(keys), values, layout); - let read_values = world.entity(selector, keys, layout); + let read_values = world.entity(selector, dojo::model::ModelIndex::Keys(keys), layout); assert_array(read_values, values); } @@ -1085,9 +1100,9 @@ fn test_set_entity_with_nested_elements() { let values = create_struct_nested_model(); let layout = dojo::model::Model::::layout(); - world.set_entity(selector, keys, values, layout); + world.set_entity(selector, dojo::model::ModelIndex::Keys(keys), values, layout); - let read_values = world.entity(selector, keys, layout); + let read_values = world.entity(selector, dojo::model::ModelIndex::Keys(keys), layout); assert_array(read_values, values); } @@ -1113,19 +1128,38 @@ fn test_set_entity_with_struct_generics_enum_layout() { let layout = dojo::model::Model::::layout(); // test with the first variant - world.set_entity(selector, keys, values, layout); + world.set_entity(selector, dojo::model::ModelIndex::Keys(keys), values, layout); - let read_values = world.entity(selector, keys, layout); + let read_values = world.entity(selector, dojo::model::ModelIndex::Keys(keys), layout); assert_array(read_values, values); // then override with the second variant let values = create_struct_generic_second_variant(); - world.set_entity(selector, keys, values, layout); + world.set_entity(selector, dojo::model::ModelIndex::Keys(keys), values, layout); - let read_values = world.entity(selector, keys, layout); + let read_values = world.entity(selector, dojo::model::ModelIndex::Keys(keys), layout); assert_array(read_values, values); } +#[test] +fn test_delete_entity_by_id() { + let world = deploy_world(); + world.register_model(foo::TEST_CLASS_HASH.try_into().unwrap()); + let selector = dojo::model::Model::::selector(); + let entity_id = entity_id_from_keys(get_key_test()); + let values = create_foo(); + let layout = dojo::model::Model::::layout(); + + world.set_entity(selector, dojo::model::ModelIndex::Id(entity_id), values, layout); + + world.delete_entity(selector, dojo::model::ModelIndex::Id(entity_id), layout); + + let read_values = world.entity(selector, dojo::model::ModelIndex::Id(entity_id), layout); + + assert!(read_values.len() == values.len()); + assert_empty_array(read_values); +} + #[test] fn test_delete_entity_with_fixed_layout() { let world = deploy_world(); @@ -1135,11 +1169,11 @@ fn test_delete_entity_with_fixed_layout() { let values = create_foo(); let layout = dojo::model::Model::::layout(); - world.set_entity(selector, get_key_test(), values, layout); + world.set_entity(selector, dojo::model::ModelIndex::Keys(get_key_test()), values, layout); - world.delete_entity(selector, keys, layout); + world.delete_entity(selector, dojo::model::ModelIndex::Keys(keys), layout); - let read_values = world.entity(selector, keys, layout); + let read_values = world.entity(selector, dojo::model::ModelIndex::Keys(keys), layout); assert!(read_values.len() == values.len()); assert_empty_array(read_values); @@ -1155,11 +1189,11 @@ fn test_delete_entity_with_simple_struct_layout() { let values = create_struct_simple_model(); let layout = dojo::model::Model::::layout(); - world.set_entity(selector, keys, values, layout); + world.set_entity(selector, dojo::model::ModelIndex::Keys(keys), values, layout); - world.delete_entity(selector, keys, layout); + world.delete_entity(selector, dojo::model::ModelIndex::Keys(keys), layout); - let read_values = world.entity(selector, keys, layout); + let read_values = world.entity(selector, dojo::model::ModelIndex::Keys(keys), layout); assert!(read_values.len() == values.len()); assert_empty_array(read_values); @@ -1175,11 +1209,11 @@ fn test_delete_entity_with_struct_simple_array_layout() { let values = create_struct_simple_array_model(); let layout = dojo::model::Model::::layout(); - world.set_entity(selector, keys, values, layout); + world.set_entity(selector, dojo::model::ModelIndex::Keys(keys), values, layout); - world.delete_entity(selector, keys, layout); + world.delete_entity(selector, dojo::model::ModelIndex::Keys(keys), layout); - let read_values = world.entity(selector, keys, layout); + let read_values = world.entity(selector, dojo::model::ModelIndex::Keys(keys), layout); // array length set to 0, so the expected value span is shorter than the initial values let expected_values = array![0, 0, 0].span(); @@ -1199,11 +1233,11 @@ fn test_delete_entity_with_complex_array_struct_layout() { let layout = dojo::model::Model::::layout(); - world.set_entity(selector, keys, values, layout); + world.set_entity(selector, dojo::model::ModelIndex::Keys(keys), values, layout); - world.delete_entity(selector, keys, layout); + world.delete_entity(selector, dojo::model::ModelIndex::Keys(keys), layout); - let read_values = world.entity(selector, keys, layout); + let read_values = world.entity(selector, dojo::model::ModelIndex::Keys(keys), layout); // array length set to 0, so the expected value span is shorter than the initial values let expected_values = array![0, 0, 0, 0, 0, 0, 0, 0, 0, 0].span(); @@ -1222,12 +1256,12 @@ fn test_delete_entity_with_struct_tuple_layout() { let values = create_struct_with_tuple(); let layout = dojo::model::Model::::layout(); - world.set_entity(selector, keys, values, layout); + world.set_entity(selector, dojo::model::ModelIndex::Keys(keys), values, layout); - world.delete_entity(selector, keys, layout); + world.delete_entity(selector, dojo::model::ModelIndex::Keys(keys), layout); let expected_values = array![0, 0].span(); - let read_values = world.entity(selector, keys, layout); + let read_values = world.entity(selector, dojo::model::ModelIndex::Keys(keys), layout); assert!(read_values.len() == expected_values.len()); assert_empty_array(read_values); @@ -1244,12 +1278,12 @@ fn test_delete_entity_with_struct_enum_layout() { let layout = dojo::model::Model::::layout(); // test with the first variant - world.set_entity(selector, keys, values, layout); + world.set_entity(selector, dojo::model::ModelIndex::Keys(keys), values, layout); - world.delete_entity(selector, keys, layout); + world.delete_entity(selector, dojo::model::ModelIndex::Keys(keys), layout); let expected_values = array![0, 0, 0].span(); - let read_values = world.entity(selector, keys, layout); + let read_values = world.entity(selector, dojo::model::ModelIndex::Keys(keys), layout); assert!(read_values.len() == expected_values.len()); assert_empty_array(read_values); @@ -1265,12 +1299,12 @@ fn test_delete_entity_with_struct_layout_and_byte_array() { let values = create_struct_byte_array_model(); let layout = dojo::model::Model::::layout(); - world.set_entity(selector, keys, values, layout); + world.set_entity(selector, dojo::model::ModelIndex::Keys(keys), values, layout); - world.delete_entity(selector, keys, layout); + world.delete_entity(selector, dojo::model::ModelIndex::Keys(keys), layout); let expected_values = array![0, 0, 0, 0].span(); - let read_values = world.entity(selector, keys, layout); + let read_values = world.entity(selector, dojo::model::ModelIndex::Keys(keys), layout); assert!(read_values.len() == expected_values.len()); assert_empty_array(read_values); @@ -1286,12 +1320,12 @@ fn test_delete_entity_with_nested_elements() { let values = create_struct_nested_model(); let layout = dojo::model::Model::::layout(); - world.set_entity(selector, keys, values, layout); + world.set_entity(selector, dojo::model::ModelIndex::Keys(keys), values, layout); - world.delete_entity(selector, keys, layout); + world.delete_entity(selector, dojo::model::ModelIndex::Keys(keys), layout); let expected_values = array![0, 0, 0, 0, 0, 0, 0, 0, 0].span(); - let read_values = world.entity(selector, keys, layout); + let read_values = world.entity(selector, dojo::model::ModelIndex::Keys(keys), layout); assert!(read_values.len() == expected_values.len()); assert_empty_array(read_values); @@ -1307,12 +1341,12 @@ fn test_delete_entity_with_struct_generics_enum_layout() { let values = create_struct_generic_first_variant(); let layout = dojo::model::Model::::layout(); - world.set_entity(selector, keys, values, layout); + world.set_entity(selector, dojo::model::ModelIndex::Keys(keys), values, layout); - world.delete_entity(selector, keys, layout); + world.delete_entity(selector, dojo::model::ModelIndex::Keys(keys), layout); let expected_values = array![0, 0].span(); - let read_values = world.entity(selector, keys, layout); + let read_values = world.entity(selector, dojo::model::ModelIndex::Keys(keys), layout); assert!(read_values.len() == expected_values.len()); assert_empty_array(read_values); @@ -1331,7 +1365,7 @@ fn test_set_entity_with_unexpected_array_model_layout() { world .set_entity( dojo::model::Model::::selector(), - array![].span(), + dojo::model::ModelIndex::Keys(array![].span()), array![].span(), layout ); @@ -1350,7 +1384,7 @@ fn test_set_entity_with_unexpected_tuple_model_layout() { world .set_entity( dojo::model::Model::::selector(), - array![].span(), + dojo::model::ModelIndex::Keys(array![].span()), array![].span(), layout ); @@ -1368,7 +1402,9 @@ fn test_delete_entity_with_unexpected_array_model_layout() { world .delete_entity( - dojo::model::Model::::selector(), array![].span(), layout + dojo::model::Model::::selector(), + dojo::model::ModelIndex::Keys(array![].span()), + layout ); } @@ -1384,7 +1420,9 @@ fn test_delete_entity_with_unexpected_tuple_model_layout() { world .delete_entity( - dojo::model::Model::::selector(), array![].span(), layout + dojo::model::Model::::selector(), + dojo::model::ModelIndex::Keys(array![].span()), + layout ); } @@ -1398,7 +1436,12 @@ fn test_get_entity_with_unexpected_array_model_layout() { array![dojo::database::introspect::Introspect::::layout()].span() ); - world.entity(dojo::model::Model::::selector(), array![].span(), layout); + world + .entity( + dojo::model::Model::::selector(), + dojo::model::ModelIndex::Keys(array![].span()), + layout + ); } #[test] @@ -1411,7 +1454,12 @@ fn test_get_entity_with_unexpected_tuple_model_layout() { array![dojo::database::introspect::Introspect::::layout()].span() ); - world.entity(dojo::model::Model::::selector(), array![].span(), layout); + world + .entity( + dojo::model::Model::::selector(), + dojo::model::ModelIndex::Keys(array![].span()), + layout + ); } @@ -1425,7 +1473,7 @@ fn test_set_entity_with_bad_values_length_error_for_array_layout() { let keys = get_key_test(); let layout = dojo::model::Model::::layout(); - world.set_entity(selector, keys, array![1].span(), layout); + world.set_entity(selector, dojo::model::ModelIndex::Keys(keys), array![1].span(), layout); } #[test] @@ -1442,7 +1490,7 @@ fn test_set_entity_with_too_big_array_length() { .span(); let layout = dojo::model::Model::::layout(); - world.set_entity(selector, keys, values, layout); + world.set_entity(selector, dojo::model::ModelIndex::Keys(keys), values, layout); } #[test] @@ -1459,7 +1507,7 @@ fn test_set_entity_with_struct_layout_and_bad_byte_array_length() { .span(); let layout = dojo::model::Model::::layout(); - world.set_entity(selector, keys, values, layout); + world.set_entity(selector, dojo::model::ModelIndex::Keys(keys), values, layout); } #[test] @@ -1473,7 +1521,7 @@ fn test_set_entity_with_struct_layout_and_bad_value_length_for_byte_array() { let values: Span = array![1, 3, 'first', 'second', 'third', 'pending'].span(); let layout = dojo::model::Model::::layout(); - world.set_entity(selector, keys, values, layout); + world.set_entity(selector, dojo::model::ModelIndex::Keys(keys), values, layout); } fn write_foo_record(world: dojo::world::IWorldDispatcher) { @@ -1481,7 +1529,7 @@ fn write_foo_record(world: dojo::world::IWorldDispatcher) { let values = create_foo(); let layout = dojo::model::Model::::layout(); - world.set_entity(selector, get_key_test(), values, layout); + world.set_entity(selector, dojo::model::ModelIndex::Keys(get_key_test()), values, layout); } #[test] diff --git a/crates/dojo-lang/src/inline_macros/delete.rs b/crates/dojo-lang/src/inline_macros/delete.rs index 51b3e56229..efbcc543c4 100644 --- a/crates/dojo-lang/src/inline_macros/delete.rs +++ b/crates/dojo-lang/src/inline_macros/delete.rs @@ -145,12 +145,9 @@ impl InlineMacroExprPlugin for DeleteMacro { builder.add_str(&format!( " - let __delete_macro_value__ = {}; - {}.delete_entity( - dojo::model::Model::instance_selector(@__delete_macro_value__), - dojo::model::Model::keys(@__delete_macro_value__), - dojo::model::Model::instance_layout(@__delete_macro_value__) - );", + let __delete_model_instance__ = {}; + dojo::model::Model::delete(@__delete_model_instance__, {}); + ", entity, world.as_syntax_node().get_text(db), )); diff --git a/crates/dojo-lang/src/inline_macros/get.rs b/crates/dojo-lang/src/inline_macros/get.rs index 91cba669fd..e37c9dc83e 100644 --- a/crates/dojo-lang/src/inline_macros/get.rs +++ b/crates/dojo-lang/src/inline_macros/get.rs @@ -109,9 +109,7 @@ impl InlineMacroExprPlugin for GetMacro { builder.add_str(&format!( "\n - let __{model}_layout__ = dojo::model::Model::<{model}>::layout(); - let __{model}: {model} = dojo::model::Model::entity({}, __get_macro_keys__, \ - __{model}_layout__);\n", + let __{model}: {model} = dojo::model::Model::get({}, __get_macro_keys__);\n", world.as_syntax_node().get_text(db), )); } diff --git a/crates/dojo-lang/src/inline_macros/set.rs b/crates/dojo-lang/src/inline_macros/set.rs index 493384644e..7c7c5d3925 100644 --- a/crates/dojo-lang/src/inline_macros/set.rs +++ b/crates/dojo-lang/src/inline_macros/set.rs @@ -160,12 +160,8 @@ impl InlineMacroExprPlugin for SetMacro { builder.add_str(&format!( " let __set_model_instance__ = {}; - {}.set_entity( - dojo::model::Model::instance_selector(@__set_model_instance__), - dojo::model::Model::keys(@__set_model_instance__), - dojo::model::Model::values(@__set_model_instance__), - dojo::model::Model::instance_layout(@__set_model_instance__), - );", + dojo::model::Model::set(@__set_model_instance__, {}); + ", entity, world.as_syntax_node().get_text(db), )); diff --git a/crates/dojo-lang/src/introspect/layout.rs b/crates/dojo-lang/src/introspect/layout.rs index 216b00678c..9a8b929965 100644 --- a/crates/dojo-lang/src/introspect/layout.rs +++ b/crates/dojo-lang/src/introspect/layout.rs @@ -27,7 +27,7 @@ pub fn build_field_layouts( } let field_name = m.name(db).text(db); - let field_selector = get_selector_from_name(field_name.as_str()).unwrap().to_string(); + let field_selector = get_selector_from_name(&field_name.to_string()).unwrap(); let field_layout = get_layout_from_type_clause(db, diagnostics, &m.type_clause(db)); Some(format!( "dojo::database::introspect::FieldLayout {{ diff --git a/crates/dojo-lang/src/manifest_test_data/compiler_cairo/manifests/dev/base/abis/dojo-world.json b/crates/dojo-lang/src/manifest_test_data/compiler_cairo/manifests/dev/base/abis/dojo-world.json index 0e5e96210e..6dd9a18e1a 100644 --- a/crates/dojo-lang/src/manifest_test_data/compiler_cairo/manifests/dev/base/abis/dojo-world.json +++ b/crates/dojo-lang/src/manifest_test_data/compiler_cairo/manifests/dev/base/abis/dojo-world.json @@ -46,6 +46,24 @@ } ] }, + { + "type": "enum", + "name": "dojo::world::ModelIndex", + "variants": [ + { + "name": "Keys", + "type": "core::array::Span::" + }, + { + "name": "Id", + "type": "core::felt252" + }, + { + "name": "MemberId", + "type": "(core::felt252, core::felt252)" + } + ] + }, { "type": "struct", "name": "core::array::Span::", @@ -282,12 +300,12 @@ "name": "entity", "inputs": [ { - "name": "model", + "name": "model_selector", "type": "core::felt252" }, { - "name": "keys", - "type": "core::array::Span::" + "name": "index", + "type": "dojo::world::ModelIndex" }, { "name": "layout", @@ -306,12 +324,12 @@ "name": "set_entity", "inputs": [ { - "name": "model", + "name": "model_selector", "type": "core::felt252" }, { - "name": "keys", - "type": "core::array::Span::" + "name": "index", + "type": "dojo::world::ModelIndex" }, { "name": "values", @@ -330,12 +348,12 @@ "name": "delete_entity", "inputs": [ { - "name": "model", + "name": "model_selector", "type": "core::felt252" }, { - "name": "keys", - "type": "core::array::Span::" + "name": "index", + "type": "dojo::world::ModelIndex" }, { "name": "layout", @@ -485,7 +503,7 @@ "name": "can_write_model", "inputs": [ { - "name": "model_id", + "name": "model_selector", "type": "core::felt252" }, { @@ -901,7 +919,7 @@ }, { "type": "event", - "name": "dojo::world::world::StoreDelRecord", + "name": "dojo::world::world::StoreUpdateRecord", "kind": "struct", "members": [ { @@ -910,12 +928,34 @@ "kind": "data" }, { - "name": "keys", + "name": "entity_id", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "values", "type": "core::array::Span::", "kind": "data" } ] }, + { + "type": "event", + "name": "dojo::world::world::StoreDelRecord", + "kind": "struct", + "members": [ + { + "name": "table", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "entity_id", + "type": "core::felt252", + "kind": "data" + } + ] + }, { "type": "event", "name": "dojo::world::world::WriterUpdated", @@ -1075,6 +1115,11 @@ "type": "dojo::world::world::StoreSetRecord", "kind": "nested" }, + { + "name": "StoreUpdateRecord", + "type": "dojo::world::world::StoreUpdateRecord", + "kind": "nested" + }, { "name": "StoreDelRecord", "type": "dojo::world::world::StoreDelRecord", diff --git a/crates/dojo-lang/src/manifest_test_data/compiler_cairo/manifests/dev/base/dojo-world.toml b/crates/dojo-lang/src/manifest_test_data/compiler_cairo/manifests/dev/base/dojo-world.toml index 83a7a20228..03f06ebea5 100644 --- a/crates/dojo-lang/src/manifest_test_data/compiler_cairo/manifests/dev/base/dojo-world.toml +++ b/crates/dojo-lang/src/manifest_test_data/compiler_cairo/manifests/dev/base/dojo-world.toml @@ -1,6 +1,6 @@ kind = "Class" -class_hash = "0x210dd8e484e5555dc74a4a600b17878fc108911719b04139309acc874160c51" -original_class_hash = "0x210dd8e484e5555dc74a4a600b17878fc108911719b04139309acc874160c51" +class_hash = "0x2bcf11feac030c5ec81496dfc73ae256568c5b7518f8542e25dd0e42938de7e" +original_class_hash = "0x2bcf11feac030c5ec81496dfc73ae256568c5b7518f8542e25dd0e42938de7e" abi = "manifests/dev/base/abis/dojo-world.json" tag = "dojo-world" manifest_name = "dojo-world" diff --git a/crates/dojo-lang/src/model.rs b/crates/dojo-lang/src/model.rs index 18bdd3ed80..c2db111a94 100644 --- a/crates/dojo-lang/src/model.rs +++ b/crates/dojo-lang/src/model.rs @@ -3,7 +3,9 @@ use std::collections::HashMap; use cairo_lang_defs::patcher::RewriteNode; use cairo_lang_defs::plugin::PluginDiagnostic; use cairo_lang_diagnostics::Severity; -use cairo_lang_syntax::node::ast::{ArgClause, Expr, ItemStruct, OptionArgListParenthesized}; +use cairo_lang_syntax::node::ast::{ + ArgClause, Expr, ItemStruct, Member as MemberAst, OptionArgListParenthesized, +}; use cairo_lang_syntax::node::db::SyntaxGroup; use cairo_lang_syntax::node::helpers::QueryAttrs; use cairo_lang_syntax::node::{Terminal, TypedStablePtr, TypedSyntaxNode}; @@ -11,6 +13,7 @@ use cairo_lang_utils::unordered_hash_map::UnorderedHashMap; use convert_case::{Case, Casing}; use dojo_world::contracts::naming; use dojo_world::manifest::Member; +use starknet::core::utils::get_selector_from_name; use crate::plugin::{DojoAuxData, Model, DOJO_MODEL_ATTR}; use crate::utils::is_name_valid; @@ -236,19 +239,48 @@ pub fn handle_model_struct( ), }; + let mut members: Vec = vec![]; + let mut members_values: Vec = vec![]; + let mut param_keys: Vec = vec![]; + let mut serialized_keys: Vec = vec![]; + let mut serialized_param_keys: Vec = vec![]; + let mut serialized_values: Vec = vec![]; + let mut field_accessors: Vec = vec![]; + let mut entity_field_accessors: Vec = vec![]; let elements = struct_ast.members(db).elements(db); - let members: &Vec<_> = &elements - .iter() - .map(|member| Member { - name: member.name(db).text(db).to_string(), - ty: member.type_clause(db).ty(db).as_syntax_node().get_text(db).trim().to_string(), - key: member.has_attr(db, "key"), - }) - .collect::<_>(); - let keys: Vec<_> = members.iter().filter(|m| m.key).collect::<_>(); + elements.iter().for_each(|member_ast| { + let member = Member { + name: member_ast.name(db).text(db).to_string(), + ty: member_ast.type_clause(db).ty(db).as_syntax_node().get_text(db).trim().to_string(), + key: member_ast.has_attr(db, "key"), + }; + + if member.key { + validate_key_member(&member, db, member_ast, &mut diagnostics); + serialized_keys.push(serialize_member_ty(&member, true)); + serialized_param_keys.push(serialize_member_ty(&member, false)); + param_keys.push(format!("{}: {}", member.name, member.ty)); + } else { + serialized_values.push(serialize_member_ty(&member, true)); + members_values.push(RewriteNode::Text(format!("{}: {},\n", member.name, member.ty))); + } + + members.push(member); + }); + let param_keys = param_keys.join(", "); + + members.iter().filter(|m| !m.key).for_each(|member| { + field_accessors.push(generate_field_accessors( + model_name.clone(), + param_keys.clone(), + serialized_param_keys.clone(), + member, + )); + entity_field_accessors.push(generate_entity_field_accessors(model_name.clone(), member)); + }); - if keys.is_empty() { + if serialized_keys.is_empty() { diagnostics.push(PluginDiagnostic { message: "Model must define at least one #[key] attribute".into(), stable_ptr: struct_ast.name(db).stable_ptr().untyped(), @@ -256,7 +288,7 @@ pub fn handle_model_struct( }); } - if keys.len() == members.len() { + if serialized_values.is_empty() { diagnostics.push(PluginDiagnostic { message: "Model must define at least one member that is not a key".into(), stable_ptr: struct_ast.name(db).stable_ptr().untyped(), @@ -264,60 +296,156 @@ pub fn handle_model_struct( }); } - for k in &keys { - if k.ty == "u256" { - diagnostics.push(PluginDiagnostic { - message: "Key is only supported for core types that are 1 felt long once \ - serialized. `u256` is a struct of 2 u128, hence not supported." - .into(), - stable_ptr: struct_ast.name(db).stable_ptr().untyped(), - severity: Severity::Error, - }); - } - } - - let serialize_member = |m: &Member, include_key: bool| { - if m.key && !include_key { - return None; - } - - if m.ty == "felt252" { - return Some(RewriteNode::Text(format!( - "core::array::ArrayTrait::append(ref serialized, *self.{});", - m.name - ))); - } - - Some(RewriteNode::Text(format!( - "core::serde::Serde::serialize(self.{}, ref serialized);", - m.name - ))) - }; - - let serialized_keys: Vec<_> = - keys.iter().filter_map(|m| serialize_member(m, true)).collect::<_>(); - - let serialized_values: Vec<_> = - members.iter().filter_map(|m| serialize_member(m, false)).collect::<_>(); - let name = struct_ast.name(db).text(db); aux_data.models.push(Model { name: name.to_string(), namespace: model_namespace.clone(), - members: members.to_vec(), + members, }); ( RewriteNode::interpolate_patched( " -impl $type_name$Model of dojo::model::Model<$type_name$> { - fn entity(world: dojo::world::IWorldDispatcher, keys: Span, layout: \ - dojo::database::introspect::Layout) -> $type_name$ { +#[derive(Drop, Serde)] +pub struct $type_name$Entity { + __id: felt252, // private field + $members_values$ +} + +#[generate_trait] +impl $type_name$EntityImpl of $type_name$EntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> $type_name$Entity { + $type_name$ModelEntityImpl::get(world, entity_id) + } + + $entity_field_accessors$ +} + +#[generate_trait] +impl $type_name$Impl of $type_name$Trait { + fn entity_id_from_keys($param_keys$) -> felt252 { + let mut serialized = core::array::ArrayTrait::new(); + $serialized_param_keys$ + core::poseidon::poseidon_hash_span(serialized.span()) + } + + fn get(world: dojo::world::IWorldDispatcher, $param_keys$) -> $type_name$ { + let mut serialized = core::array::ArrayTrait::new(); + $serialized_param_keys$ + + dojo::model::Model::<$type_name$>::get(world, serialized.span()) + } + + $field_accessors$ +} + +impl $type_name$ModelEntityImpl of dojo::model::ModelEntity<$type_name$Entity> { + fn id(self: @$type_name$Entity) -> felt252 { + *self.__id + } + + fn values(self: @$type_name$Entity) -> Span { + let mut serialized = core::array::ArrayTrait::new(); + $serialized_values$ + core::array::ArrayTrait::span(@serialized) + } + + fn from_values(entity_id: felt252, values: Span) -> $type_name$Entity { + let mut serialized = array![entity_id]; + let mut i = 0; + loop { + if i >= values.len() { break; } + serialized.append(*values.at(i)); + i += 1; + }; + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let entity_values = core::serde::Serde::<$type_name$Entity>::deserialize(ref serialized); + if core::option::OptionTrait::<$type_name$Entity>::is_none(@entity_values) { + panic!( + \"ModelEntity `$type_name$Entity`: deserialization failed.\" + ); + } + core::option::OptionTrait::<$type_name$Entity>::unwrap(entity_values) + } + + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> $type_name$Entity { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::<$type_name$>::selector(), + dojo::world::ModelIndex::Id(entity_id), + dojo::model::Model::<$type_name$>::layout() + ); + Self::from_values(entity_id, values) + } + + fn update(self: @$type_name$Entity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::<$type_name$>::selector(), + dojo::world::ModelIndex::Id(self.id()), + self.values(), + dojo::model::Model::<$type_name$>::layout() + ); + } + + fn delete(self: @$type_name$Entity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + dojo::model::Model::<$type_name$>::selector(), + dojo::world::ModelIndex::Id(self.id()), + dojo::model::Model::<$type_name$>::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + entity_id: felt252, + member_id: felt252, + ) -> Span { + match dojo::utils::find_model_field_layout(dojo::model::Model::<$type_name$>::layout(), \ + member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::<$type_name$>::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @$type_name$Entity, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span, + ) { + match dojo::utils::find_model_field_layout(dojo::model::Model::<$type_name$>::layout(), \ + member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::<$type_name$>::selector(), + dojo::world::ModelIndex::MemberId((self.id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } +} + +impl $type_name$ModelImpl of dojo::model::Model<$type_name$> { + fn get(world: dojo::world::IWorldDispatcher, keys: Span) -> $type_name$ { let values = dojo::world::IWorldDispatcherTrait::entity( world, Self::selector(), - keys, - layout + dojo::world::ModelIndex::Keys(keys), + Self::layout() ); // TODO: Generate method to deserialize from keys / values directly to avoid @@ -339,6 +467,70 @@ impl $type_name$Model of dojo::model::Model<$type_name$> { core::option::OptionTrait::<$type_name$>::unwrap(entity) } + fn set( + self: @$type_name$, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::values(self), + Self::layout() + ); + } + + fn delete( + self: @$type_name$, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + keys: Span, + member_id: felt252 + ) -> Span { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + let entity_id = dojo::utils::entity_id_from_keys(keys); + dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @$type_name$, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span + ) { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((self.entity_id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + #[inline(always)] fn name() -> ByteArray { \"$type_name$\" @@ -378,7 +570,12 @@ impl $type_name$Model of dojo::model::Model<$type_name$> { fn namespace_hash() -> felt252 { $model_namespace_hash$ } - + + #[inline(always)] + fn entity_id(self: @$type_name$) -> felt252 { + core::poseidon::poseidon_hash_span(self.keys()) + } + #[inline(always)] fn keys(self: @$type_name$) -> Span { let mut serialized = core::array::ArrayTrait::new(); @@ -503,8 +700,196 @@ mod $contract_name$ { RewriteNode::Text(model_namespace_hash.to_string()), ), ("model_tag".to_string(), RewriteNode::Text(model_tag.clone())), + ("members_values".to_string(), RewriteNode::new_modified(members_values)), + ("param_keys".to_string(), RewriteNode::Text(param_keys)), + ( + "serialized_param_keys".to_string(), + RewriteNode::new_modified(serialized_param_keys), + ), + ("field_accessors".to_string(), RewriteNode::new_modified(field_accessors)), + ( + "entity_field_accessors".to_string(), + RewriteNode::new_modified(entity_field_accessors), + ), ]), ), diagnostics, ) } + +/// Validates that the key member is valid. +/// # Arguments +/// +/// * member: The member to validate. +/// * diagnostics: The diagnostics to push to, if the member is an invalid key. +fn validate_key_member( + member: &Member, + db: &dyn SyntaxGroup, + member_ast: &MemberAst, + diagnostics: &mut Vec, +) { + if member.ty == "u256" { + diagnostics.push(PluginDiagnostic { + message: "Key is only supported for core types that are 1 felt long once serialized. \ + `u256` is a struct of 2 u128, hence not supported." + .into(), + stable_ptr: member_ast.name(db).stable_ptr().untyped(), + severity: Severity::Error, + }); + } +} + +/// Creates a [`RewriteNode`] for the member type serialization. +/// +/// # Arguments +/// +/// * member: The member to serialize. +fn serialize_member_ty(member: &Member, with_self: bool) -> RewriteNode { + match member.ty.as_str() { + "felt252" => RewriteNode::Text(format!( + "core::array::ArrayTrait::append(ref serialized, {}{});\n", + if with_self { "*self." } else { "" }, + member.name + )), + _ => RewriteNode::Text(format!( + "core::serde::Serde::serialize({}{}, ref serialized);\n", + if with_self { "self." } else { "@" }, + member.name + )), + } +} + +/// Generates field accessors (`get_[field_name]` and `set_[field_name]`) for every +/// fields of a model. +/// +/// # Arguments +/// +/// * `model_name` - the model name. +/// * `param_keys` - coma separated model keys with the format `KEY_NAME: KEY_TYPE`. +/// * `serialized_param_keys` - code to serialize model keys in a `serialized` felt252 array. +/// * `member` - information about the field for which to generate accessors. +/// +/// # Returns +/// A [`RewriteNode`] containing accessors code. +fn generate_field_accessors( + model_name: String, + param_keys: String, + serialized_param_keys: Vec, + member: &Member, +) -> RewriteNode { + RewriteNode::interpolate_patched( + " + fn get_$field_name$(world: dojo::world::IWorldDispatcher, $param_keys$) -> $field_type$ { + let mut serialized = core::array::ArrayTrait::new(); + $serialized_param_keys$ + + let values = dojo::model::Model::<$model_name$>::get_member( + world, + serialized.span(), + $field_selector$ + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::<$field_type$>::deserialize(ref serialized); + + if core::option::OptionTrait::<$field_type$>::is_none(@field_value) { + panic!( + \"Field `$model_name$::$field_name$`: deserialization failed.\" + ); + } + + core::option::OptionTrait::<$field_type$>::unwrap(field_value) + } + + fn set_$field_name$(self: @$model_name$, world: dojo::world::IWorldDispatcher, value: \ + $field_type$) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + $field_selector$, + serialized.span() + ); + } + ", + &UnorderedHashMap::from([ + ("model_name".to_string(), RewriteNode::Text(model_name)), + ( + "field_selector".to_string(), + RewriteNode::Text( + get_selector_from_name(&member.name).expect("invalid member name").to_string(), + ), + ), + ("field_name".to_string(), RewriteNode::Text(member.name.clone())), + ("field_type".to_string(), RewriteNode::Text(member.ty.clone())), + ("param_keys".to_string(), RewriteNode::Text(param_keys)), + ("serialized_param_keys".to_string(), RewriteNode::new_modified(serialized_param_keys)), + ]), + ) +} + +/// Generates field accessors (`get_[field_name]` and `set_[field_name]`) for every +/// fields of a model entity. +/// +/// # Arguments +/// +/// * `model_name` - the model name. +/// * `member` - information about the field for which to generate accessors. +/// +/// # Returns +/// A [`RewriteNode`] containing accessors code. +fn generate_entity_field_accessors(model_name: String, member: &Member) -> RewriteNode { + RewriteNode::interpolate_patched( + " + fn get_$field_name$(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> $field_type$ \ + { + let values = dojo::model::ModelEntity::<$model_name$Entity>::get_member( + world, + entity_id, + $field_selector$ + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::<$field_type$>::deserialize(ref serialized); + + if core::option::OptionTrait::<$field_type$>::is_none(@field_value) { + panic!( + \"Field `$model_name$::$field_name$`: deserialization failed.\" + ); + } + + core::option::OptionTrait::<$field_type$>::unwrap(field_value) + } + + fn set_$field_name$(self: @$model_name$Entity, world: dojo::world::IWorldDispatcher, value: \ + $field_type$) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + $field_selector$, + serialized.span() + ); + } +", + &UnorderedHashMap::from([ + ("model_name".to_string(), RewriteNode::Text(model_name)), + ( + "field_selector".to_string(), + RewriteNode::Text( + get_selector_from_name(&member.name).expect("invalid member name").to_string(), + ), + ), + ("field_name".to_string(), RewriteNode::Text(member.name.clone())), + ("field_type".to_string(), RewriteNode::Text(member.ty.clone())), + ]), + ) +} diff --git a/crates/dojo-lang/src/plugin_test_data/model b/crates/dojo-lang/src/plugin_test_data/model index fd85ef4652..5aa4788092 100644 --- a/crates/dojo-lang/src/plugin_test_data/model +++ b/crates/dojo-lang/src/plugin_test_data/model @@ -395,13 +395,218 @@ dojo::database::introspect::Member { } } -impl BadModelMultipleVersionsModel of dojo::model::Model { - fn entity(world: dojo::world::IWorldDispatcher, keys: Span, layout: dojo::database::introspect::Layout) -> BadModelMultipleVersions { +#[derive(Drop, Serde)] +pub struct BadModelMultipleVersionsEntity { + __id: felt252, // private field + v: Vec3, + +} + +#[generate_trait] +impl BadModelMultipleVersionsEntityImpl of BadModelMultipleVersionsEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> BadModelMultipleVersionsEntity { + BadModelMultipleVersionsModelEntityImpl::get(world, entity_id) + } + + + fn get_v(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Vec3 { + let values = dojo::model::ModelEntity::::get_member( + world, + entity_id, + 578691550836206188651404750433984985630363913126316857592149308417275000080 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `BadModelMultipleVersions::v`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_v(self: @BadModelMultipleVersionsEntity, world: dojo::world::IWorldDispatcher, value: Vec3) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 578691550836206188651404750433984985630363913126316857592149308417275000080, + serialized.span() + ); + } + +} + +#[generate_trait] +impl BadModelMultipleVersionsImpl of BadModelMultipleVersionsTrait { + fn entity_id_from_keys(id: felt252) -> felt252 { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + core::poseidon::poseidon_hash_span(serialized.span()) + } + + fn get(world: dojo::world::IWorldDispatcher, id: felt252) -> BadModelMultipleVersions { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + + dojo::model::Model::::get(world, serialized.span()) + } + + + fn get_v(world: dojo::world::IWorldDispatcher, id: felt252) -> Vec3 { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + + let values = dojo::model::Model::::get_member( + world, + serialized.span(), + 578691550836206188651404750433984985630363913126316857592149308417275000080 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `BadModelMultipleVersions::v`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_v(self: @BadModelMultipleVersions, world: dojo::world::IWorldDispatcher, value: Vec3) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 578691550836206188651404750433984985630363913126316857592149308417275000080, + serialized.span() + ); + } + +} + +impl BadModelMultipleVersionsModelEntityImpl of dojo::model::ModelEntity { + fn id(self: @BadModelMultipleVersionsEntity) -> felt252 { + *self.__id + } + + fn values(self: @BadModelMultipleVersionsEntity) -> Span { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(self.v, ref serialized); + + core::array::ArrayTrait::span(@serialized) + } + + fn from_values(entity_id: felt252, values: Span) -> BadModelMultipleVersionsEntity { + let mut serialized = array![entity_id]; + let mut i = 0; + loop { + if i >= values.len() { break; } + serialized.append(*values.at(i)); + i += 1; + }; + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let entity_values = core::serde::Serde::::deserialize(ref serialized); + if core::option::OptionTrait::::is_none(@entity_values) { + panic!( + "ModelEntity `BadModelMultipleVersionsEntity`: deserialization failed." + ); + } + core::option::OptionTrait::::unwrap(entity_values) + } + + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> BadModelMultipleVersionsEntity { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(entity_id), + dojo::model::Model::::layout() + ); + Self::from_values(entity_id, values) + } + + fn update(self: @BadModelMultipleVersionsEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + self.values(), + dojo::model::Model::::layout() + ); + } + + fn delete(self: @BadModelMultipleVersionsEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + dojo::model::Model::::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + entity_id: felt252, + member_id: felt252, + ) -> Span { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @BadModelMultipleVersionsEntity, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span, + ) { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((self.id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } +} + +impl BadModelMultipleVersionsModelImpl of dojo::model::Model { + fn get(world: dojo::world::IWorldDispatcher, keys: Span) -> BadModelMultipleVersions { let values = dojo::world::IWorldDispatcherTrait::entity( world, Self::selector(), - keys, - layout + dojo::world::ModelIndex::Keys(keys), + Self::layout() ); // TODO: Generate method to deserialize from keys / values directly to avoid @@ -422,6 +627,70 @@ impl BadModelMultipleVersionsModel of dojo::model::Model::unwrap(entity) } + fn set( + self: @BadModelMultipleVersions, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::values(self), + Self::layout() + ); + } + + fn delete( + self: @BadModelMultipleVersions, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + keys: Span, + member_id: felt252 + ) -> Span { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + let entity_id = dojo::utils::entity_id_from_keys(keys); + dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @BadModelMultipleVersions, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span + ) { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((self.entity_id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + #[inline(always)] fn name() -> ByteArray { "BadModelMultipleVersions" @@ -461,11 +730,17 @@ impl BadModelMultipleVersionsModel of dojo::model::Model felt252 { 3437408695301308226171664635441698996501144546809569617702850025816833723775 } - + + #[inline(always)] + fn entity_id(self: @BadModelMultipleVersions) -> felt252 { + core::poseidon::poseidon_hash_span(self.keys()) + } + #[inline(always)] fn keys(self: @BadModelMultipleVersions) -> Span { let mut serialized = core::array::ArrayTrait::new(); core::array::ArrayTrait::append(ref serialized, *self.id); + core::array::ArrayTrait::span(@serialized) } @@ -473,6 +748,7 @@ impl BadModelMultipleVersionsModel of dojo::model::Model Span { let mut serialized = core::array::ArrayTrait::new(); core::serde::Serde::serialize(self.v, ref serialized); + core::array::ArrayTrait::span(@serialized) } @@ -612,13 +888,218 @@ dojo::database::introspect::Member { } } -impl BadModelBadVersionTypeModel of dojo::model::Model { - fn entity(world: dojo::world::IWorldDispatcher, keys: Span, layout: dojo::database::introspect::Layout) -> BadModelBadVersionType { +#[derive(Drop, Serde)] +pub struct BadModelBadVersionTypeEntity { + __id: felt252, // private field + v: Vec3, + +} + +#[generate_trait] +impl BadModelBadVersionTypeEntityImpl of BadModelBadVersionTypeEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> BadModelBadVersionTypeEntity { + BadModelBadVersionTypeModelEntityImpl::get(world, entity_id) + } + + + fn get_v(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Vec3 { + let values = dojo::model::ModelEntity::::get_member( + world, + entity_id, + 578691550836206188651404750433984985630363913126316857592149308417275000080 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `BadModelBadVersionType::v`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_v(self: @BadModelBadVersionTypeEntity, world: dojo::world::IWorldDispatcher, value: Vec3) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 578691550836206188651404750433984985630363913126316857592149308417275000080, + serialized.span() + ); + } + +} + +#[generate_trait] +impl BadModelBadVersionTypeImpl of BadModelBadVersionTypeTrait { + fn entity_id_from_keys(id: felt252) -> felt252 { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + core::poseidon::poseidon_hash_span(serialized.span()) + } + + fn get(world: dojo::world::IWorldDispatcher, id: felt252) -> BadModelBadVersionType { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + + dojo::model::Model::::get(world, serialized.span()) + } + + + fn get_v(world: dojo::world::IWorldDispatcher, id: felt252) -> Vec3 { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + + let values = dojo::model::Model::::get_member( + world, + serialized.span(), + 578691550836206188651404750433984985630363913126316857592149308417275000080 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `BadModelBadVersionType::v`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_v(self: @BadModelBadVersionType, world: dojo::world::IWorldDispatcher, value: Vec3) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 578691550836206188651404750433984985630363913126316857592149308417275000080, + serialized.span() + ); + } + +} + +impl BadModelBadVersionTypeModelEntityImpl of dojo::model::ModelEntity { + fn id(self: @BadModelBadVersionTypeEntity) -> felt252 { + *self.__id + } + + fn values(self: @BadModelBadVersionTypeEntity) -> Span { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(self.v, ref serialized); + + core::array::ArrayTrait::span(@serialized) + } + + fn from_values(entity_id: felt252, values: Span) -> BadModelBadVersionTypeEntity { + let mut serialized = array![entity_id]; + let mut i = 0; + loop { + if i >= values.len() { break; } + serialized.append(*values.at(i)); + i += 1; + }; + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let entity_values = core::serde::Serde::::deserialize(ref serialized); + if core::option::OptionTrait::::is_none(@entity_values) { + panic!( + "ModelEntity `BadModelBadVersionTypeEntity`: deserialization failed." + ); + } + core::option::OptionTrait::::unwrap(entity_values) + } + + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> BadModelBadVersionTypeEntity { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(entity_id), + dojo::model::Model::::layout() + ); + Self::from_values(entity_id, values) + } + + fn update(self: @BadModelBadVersionTypeEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + self.values(), + dojo::model::Model::::layout() + ); + } + + fn delete(self: @BadModelBadVersionTypeEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + dojo::model::Model::::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + entity_id: felt252, + member_id: felt252, + ) -> Span { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @BadModelBadVersionTypeEntity, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span, + ) { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((self.id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } +} + +impl BadModelBadVersionTypeModelImpl of dojo::model::Model { + fn get(world: dojo::world::IWorldDispatcher, keys: Span) -> BadModelBadVersionType { let values = dojo::world::IWorldDispatcherTrait::entity( world, Self::selector(), - keys, - layout + dojo::world::ModelIndex::Keys(keys), + Self::layout() ); // TODO: Generate method to deserialize from keys / values directly to avoid @@ -639,6 +1120,70 @@ impl BadModelBadVersionTypeModel of dojo::model::Model { core::option::OptionTrait::::unwrap(entity) } + fn set( + self: @BadModelBadVersionType, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::values(self), + Self::layout() + ); + } + + fn delete( + self: @BadModelBadVersionType, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + keys: Span, + member_id: felt252 + ) -> Span { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + let entity_id = dojo::utils::entity_id_from_keys(keys); + dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @BadModelBadVersionType, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span + ) { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((self.entity_id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + #[inline(always)] fn name() -> ByteArray { "BadModelBadVersionType" @@ -678,11 +1223,17 @@ impl BadModelBadVersionTypeModel of dojo::model::Model { fn namespace_hash() -> felt252 { 3437408695301308226171664635441698996501144546809569617702850025816833723775 } - + + #[inline(always)] + fn entity_id(self: @BadModelBadVersionType) -> felt252 { + core::poseidon::poseidon_hash_span(self.keys()) + } + #[inline(always)] fn keys(self: @BadModelBadVersionType) -> Span { let mut serialized = core::array::ArrayTrait::new(); core::array::ArrayTrait::append(ref serialized, *self.id); + core::array::ArrayTrait::span(@serialized) } @@ -690,6 +1241,7 @@ impl BadModelBadVersionTypeModel of dojo::model::Model { fn values(self: @BadModelBadVersionType) -> Span { let mut serialized = core::array::ArrayTrait::new(); core::serde::Serde::serialize(self.v, ref serialized); + core::array::ArrayTrait::span(@serialized) } @@ -829,16 +1381,221 @@ dojo::database::introspect::Member { } } -impl BadModelNoVersionValueModel of dojo::model::Model { - fn entity(world: dojo::world::IWorldDispatcher, keys: Span, layout: dojo::database::introspect::Layout) -> BadModelNoVersionValue { - let values = dojo::world::IWorldDispatcherTrait::entity( +#[derive(Drop, Serde)] +pub struct BadModelNoVersionValueEntity { + __id: felt252, // private field + v: Vec3, + +} + +#[generate_trait] +impl BadModelNoVersionValueEntityImpl of BadModelNoVersionValueEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> BadModelNoVersionValueEntity { + BadModelNoVersionValueModelEntityImpl::get(world, entity_id) + } + + + fn get_v(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Vec3 { + let values = dojo::model::ModelEntity::::get_member( world, - Self::selector(), - keys, - layout + entity_id, + 578691550836206188651404750433984985630363913126316857592149308417275000080 ); - // TODO: Generate method to deserialize from keys / values directly to avoid + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `BadModelNoVersionValue::v`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_v(self: @BadModelNoVersionValueEntity, world: dojo::world::IWorldDispatcher, value: Vec3) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 578691550836206188651404750433984985630363913126316857592149308417275000080, + serialized.span() + ); + } + +} + +#[generate_trait] +impl BadModelNoVersionValueImpl of BadModelNoVersionValueTrait { + fn entity_id_from_keys(id: felt252) -> felt252 { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + core::poseidon::poseidon_hash_span(serialized.span()) + } + + fn get(world: dojo::world::IWorldDispatcher, id: felt252) -> BadModelNoVersionValue { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + + dojo::model::Model::::get(world, serialized.span()) + } + + + fn get_v(world: dojo::world::IWorldDispatcher, id: felt252) -> Vec3 { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + + let values = dojo::model::Model::::get_member( + world, + serialized.span(), + 578691550836206188651404750433984985630363913126316857592149308417275000080 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `BadModelNoVersionValue::v`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_v(self: @BadModelNoVersionValue, world: dojo::world::IWorldDispatcher, value: Vec3) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 578691550836206188651404750433984985630363913126316857592149308417275000080, + serialized.span() + ); + } + +} + +impl BadModelNoVersionValueModelEntityImpl of dojo::model::ModelEntity { + fn id(self: @BadModelNoVersionValueEntity) -> felt252 { + *self.__id + } + + fn values(self: @BadModelNoVersionValueEntity) -> Span { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(self.v, ref serialized); + + core::array::ArrayTrait::span(@serialized) + } + + fn from_values(entity_id: felt252, values: Span) -> BadModelNoVersionValueEntity { + let mut serialized = array![entity_id]; + let mut i = 0; + loop { + if i >= values.len() { break; } + serialized.append(*values.at(i)); + i += 1; + }; + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let entity_values = core::serde::Serde::::deserialize(ref serialized); + if core::option::OptionTrait::::is_none(@entity_values) { + panic!( + "ModelEntity `BadModelNoVersionValueEntity`: deserialization failed." + ); + } + core::option::OptionTrait::::unwrap(entity_values) + } + + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> BadModelNoVersionValueEntity { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(entity_id), + dojo::model::Model::::layout() + ); + Self::from_values(entity_id, values) + } + + fn update(self: @BadModelNoVersionValueEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + self.values(), + dojo::model::Model::::layout() + ); + } + + fn delete(self: @BadModelNoVersionValueEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + dojo::model::Model::::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + entity_id: felt252, + member_id: felt252, + ) -> Span { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @BadModelNoVersionValueEntity, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span, + ) { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((self.id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } +} + +impl BadModelNoVersionValueModelImpl of dojo::model::Model { + fn get(world: dojo::world::IWorldDispatcher, keys: Span) -> BadModelNoVersionValue { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(keys), + Self::layout() + ); + + // TODO: Generate method to deserialize from keys / values directly to avoid // serializing to intermediate array. let mut serialized = core::array::ArrayTrait::new(); core::array::serialize_array_helper(keys, ref serialized); @@ -856,6 +1613,70 @@ impl BadModelNoVersionValueModel of dojo::model::Model { core::option::OptionTrait::::unwrap(entity) } + fn set( + self: @BadModelNoVersionValue, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::values(self), + Self::layout() + ); + } + + fn delete( + self: @BadModelNoVersionValue, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + keys: Span, + member_id: felt252 + ) -> Span { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + let entity_id = dojo::utils::entity_id_from_keys(keys); + dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @BadModelNoVersionValue, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span + ) { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((self.entity_id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + #[inline(always)] fn name() -> ByteArray { "BadModelNoVersionValue" @@ -895,11 +1716,17 @@ impl BadModelNoVersionValueModel of dojo::model::Model { fn namespace_hash() -> felt252 { 3437408695301308226171664635441698996501144546809569617702850025816833723775 } - + + #[inline(always)] + fn entity_id(self: @BadModelNoVersionValue) -> felt252 { + core::poseidon::poseidon_hash_span(self.keys()) + } + #[inline(always)] fn keys(self: @BadModelNoVersionValue) -> Span { let mut serialized = core::array::ArrayTrait::new(); core::array::ArrayTrait::append(ref serialized, *self.id); + core::array::ArrayTrait::span(@serialized) } @@ -907,6 +1734,7 @@ impl BadModelNoVersionValueModel of dojo::model::Model { fn values(self: @BadModelNoVersionValue) -> Span { let mut serialized = core::array::ArrayTrait::new(); core::serde::Serde::serialize(self.v, ref serialized); + core::array::ArrayTrait::span(@serialized) } @@ -1046,13 +1874,218 @@ dojo::database::introspect::Member { } } -impl BadModelUnexpectedArgWithValueModel of dojo::model::Model { - fn entity(world: dojo::world::IWorldDispatcher, keys: Span, layout: dojo::database::introspect::Layout) -> BadModelUnexpectedArgWithValue { +#[derive(Drop, Serde)] +pub struct BadModelUnexpectedArgWithValueEntity { + __id: felt252, // private field + v: Vec3, + +} + +#[generate_trait] +impl BadModelUnexpectedArgWithValueEntityImpl of BadModelUnexpectedArgWithValueEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> BadModelUnexpectedArgWithValueEntity { + BadModelUnexpectedArgWithValueModelEntityImpl::get(world, entity_id) + } + + + fn get_v(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Vec3 { + let values = dojo::model::ModelEntity::::get_member( + world, + entity_id, + 578691550836206188651404750433984985630363913126316857592149308417275000080 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `BadModelUnexpectedArgWithValue::v`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_v(self: @BadModelUnexpectedArgWithValueEntity, world: dojo::world::IWorldDispatcher, value: Vec3) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 578691550836206188651404750433984985630363913126316857592149308417275000080, + serialized.span() + ); + } + +} + +#[generate_trait] +impl BadModelUnexpectedArgWithValueImpl of BadModelUnexpectedArgWithValueTrait { + fn entity_id_from_keys(id: felt252) -> felt252 { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + core::poseidon::poseidon_hash_span(serialized.span()) + } + + fn get(world: dojo::world::IWorldDispatcher, id: felt252) -> BadModelUnexpectedArgWithValue { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + + dojo::model::Model::::get(world, serialized.span()) + } + + + fn get_v(world: dojo::world::IWorldDispatcher, id: felt252) -> Vec3 { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + + let values = dojo::model::Model::::get_member( + world, + serialized.span(), + 578691550836206188651404750433984985630363913126316857592149308417275000080 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `BadModelUnexpectedArgWithValue::v`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_v(self: @BadModelUnexpectedArgWithValue, world: dojo::world::IWorldDispatcher, value: Vec3) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 578691550836206188651404750433984985630363913126316857592149308417275000080, + serialized.span() + ); + } + +} + +impl BadModelUnexpectedArgWithValueModelEntityImpl of dojo::model::ModelEntity { + fn id(self: @BadModelUnexpectedArgWithValueEntity) -> felt252 { + *self.__id + } + + fn values(self: @BadModelUnexpectedArgWithValueEntity) -> Span { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(self.v, ref serialized); + + core::array::ArrayTrait::span(@serialized) + } + + fn from_values(entity_id: felt252, values: Span) -> BadModelUnexpectedArgWithValueEntity { + let mut serialized = array![entity_id]; + let mut i = 0; + loop { + if i >= values.len() { break; } + serialized.append(*values.at(i)); + i += 1; + }; + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let entity_values = core::serde::Serde::::deserialize(ref serialized); + if core::option::OptionTrait::::is_none(@entity_values) { + panic!( + "ModelEntity `BadModelUnexpectedArgWithValueEntity`: deserialization failed." + ); + } + core::option::OptionTrait::::unwrap(entity_values) + } + + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> BadModelUnexpectedArgWithValueEntity { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(entity_id), + dojo::model::Model::::layout() + ); + Self::from_values(entity_id, values) + } + + fn update(self: @BadModelUnexpectedArgWithValueEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + self.values(), + dojo::model::Model::::layout() + ); + } + + fn delete(self: @BadModelUnexpectedArgWithValueEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + dojo::model::Model::::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + entity_id: felt252, + member_id: felt252, + ) -> Span { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @BadModelUnexpectedArgWithValueEntity, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span, + ) { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((self.id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } +} + +impl BadModelUnexpectedArgWithValueModelImpl of dojo::model::Model { + fn get(world: dojo::world::IWorldDispatcher, keys: Span) -> BadModelUnexpectedArgWithValue { let values = dojo::world::IWorldDispatcherTrait::entity( world, Self::selector(), - keys, - layout + dojo::world::ModelIndex::Keys(keys), + Self::layout() ); // TODO: Generate method to deserialize from keys / values directly to avoid @@ -1073,6 +2106,70 @@ impl BadModelUnexpectedArgWithValueModel of dojo::model::Model::unwrap(entity) } + fn set( + self: @BadModelUnexpectedArgWithValue, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::values(self), + Self::layout() + ); + } + + fn delete( + self: @BadModelUnexpectedArgWithValue, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + keys: Span, + member_id: felt252 + ) -> Span { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + let entity_id = dojo::utils::entity_id_from_keys(keys); + dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @BadModelUnexpectedArgWithValue, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span + ) { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((self.entity_id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + #[inline(always)] fn name() -> ByteArray { "BadModelUnexpectedArgWithValue" @@ -1112,11 +2209,17 @@ impl BadModelUnexpectedArgWithValueModel of dojo::model::Model felt252 { 3437408695301308226171664635441698996501144546809569617702850025816833723775 } - + + #[inline(always)] + fn entity_id(self: @BadModelUnexpectedArgWithValue) -> felt252 { + core::poseidon::poseidon_hash_span(self.keys()) + } + #[inline(always)] fn keys(self: @BadModelUnexpectedArgWithValue) -> Span { let mut serialized = core::array::ArrayTrait::new(); core::array::ArrayTrait::append(ref serialized, *self.id); + core::array::ArrayTrait::span(@serialized) } @@ -1124,6 +2227,7 @@ impl BadModelUnexpectedArgWithValueModel of dojo::model::Model Span { let mut serialized = core::array::ArrayTrait::new(); core::serde::Serde::serialize(self.v, ref serialized); + core::array::ArrayTrait::span(@serialized) } @@ -1263,25 +2367,230 @@ dojo::database::introspect::Member { } } -impl BadModelUnexpectedArgModel of dojo::model::Model { - fn entity(world: dojo::world::IWorldDispatcher, keys: Span, layout: dojo::database::introspect::Layout) -> BadModelUnexpectedArg { - let values = dojo::world::IWorldDispatcherTrait::entity( +#[derive(Drop, Serde)] +pub struct BadModelUnexpectedArgEntity { + __id: felt252, // private field + v: Vec3, + +} + +#[generate_trait] +impl BadModelUnexpectedArgEntityImpl of BadModelUnexpectedArgEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> BadModelUnexpectedArgEntity { + BadModelUnexpectedArgModelEntityImpl::get(world, entity_id) + } + + + fn get_v(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Vec3 { + let values = dojo::model::ModelEntity::::get_member( world, - Self::selector(), - keys, - layout + entity_id, + 578691550836206188651404750433984985630363913126316857592149308417275000080 ); - // TODO: Generate method to deserialize from keys / values directly to avoid - // serializing to intermediate array. let mut serialized = core::array::ArrayTrait::new(); - core::array::serialize_array_helper(keys, ref serialized); core::array::serialize_array_helper(values, ref serialized); let mut serialized = core::array::ArrayTrait::span(@serialized); - let entity = core::serde::Serde::::deserialize(ref serialized); + let field_value = core::serde::Serde::::deserialize(ref serialized); - if core::option::OptionTrait::::is_none(@entity) { + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `BadModelUnexpectedArg::v`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_v(self: @BadModelUnexpectedArgEntity, world: dojo::world::IWorldDispatcher, value: Vec3) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 578691550836206188651404750433984985630363913126316857592149308417275000080, + serialized.span() + ); + } + +} + +#[generate_trait] +impl BadModelUnexpectedArgImpl of BadModelUnexpectedArgTrait { + fn entity_id_from_keys(id: felt252) -> felt252 { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + core::poseidon::poseidon_hash_span(serialized.span()) + } + + fn get(world: dojo::world::IWorldDispatcher, id: felt252) -> BadModelUnexpectedArg { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + + dojo::model::Model::::get(world, serialized.span()) + } + + + fn get_v(world: dojo::world::IWorldDispatcher, id: felt252) -> Vec3 { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + + let values = dojo::model::Model::::get_member( + world, + serialized.span(), + 578691550836206188651404750433984985630363913126316857592149308417275000080 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `BadModelUnexpectedArg::v`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_v(self: @BadModelUnexpectedArg, world: dojo::world::IWorldDispatcher, value: Vec3) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 578691550836206188651404750433984985630363913126316857592149308417275000080, + serialized.span() + ); + } + +} + +impl BadModelUnexpectedArgModelEntityImpl of dojo::model::ModelEntity { + fn id(self: @BadModelUnexpectedArgEntity) -> felt252 { + *self.__id + } + + fn values(self: @BadModelUnexpectedArgEntity) -> Span { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(self.v, ref serialized); + + core::array::ArrayTrait::span(@serialized) + } + + fn from_values(entity_id: felt252, values: Span) -> BadModelUnexpectedArgEntity { + let mut serialized = array![entity_id]; + let mut i = 0; + loop { + if i >= values.len() { break; } + serialized.append(*values.at(i)); + i += 1; + }; + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let entity_values = core::serde::Serde::::deserialize(ref serialized); + if core::option::OptionTrait::::is_none(@entity_values) { + panic!( + "ModelEntity `BadModelUnexpectedArgEntity`: deserialization failed." + ); + } + core::option::OptionTrait::::unwrap(entity_values) + } + + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> BadModelUnexpectedArgEntity { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(entity_id), + dojo::model::Model::::layout() + ); + Self::from_values(entity_id, values) + } + + fn update(self: @BadModelUnexpectedArgEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + self.values(), + dojo::model::Model::::layout() + ); + } + + fn delete(self: @BadModelUnexpectedArgEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + dojo::model::Model::::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + entity_id: felt252, + member_id: felt252, + ) -> Span { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @BadModelUnexpectedArgEntity, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span, + ) { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((self.id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } +} + +impl BadModelUnexpectedArgModelImpl of dojo::model::Model { + fn get(world: dojo::world::IWorldDispatcher, keys: Span) -> BadModelUnexpectedArg { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(keys), + Self::layout() + ); + + // TODO: Generate method to deserialize from keys / values directly to avoid + // serializing to intermediate array. + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(keys, ref serialized); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let entity = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@entity) { panic!( "Model `BadModelUnexpectedArg`: deserialization failed. Ensure the length of the keys tuple is matching the number of #[key] fields in the model struct." ); @@ -1290,6 +2599,70 @@ impl BadModelUnexpectedArgModel of dojo::model::Model { core::option::OptionTrait::::unwrap(entity) } + fn set( + self: @BadModelUnexpectedArg, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::values(self), + Self::layout() + ); + } + + fn delete( + self: @BadModelUnexpectedArg, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + keys: Span, + member_id: felt252 + ) -> Span { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + let entity_id = dojo::utils::entity_id_from_keys(keys); + dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @BadModelUnexpectedArg, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span + ) { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((self.entity_id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + #[inline(always)] fn name() -> ByteArray { "BadModelUnexpectedArg" @@ -1329,11 +2702,17 @@ impl BadModelUnexpectedArgModel of dojo::model::Model { fn namespace_hash() -> felt252 { 3437408695301308226171664635441698996501144546809569617702850025816833723775 } - + + #[inline(always)] + fn entity_id(self: @BadModelUnexpectedArg) -> felt252 { + core::poseidon::poseidon_hash_span(self.keys()) + } + #[inline(always)] fn keys(self: @BadModelUnexpectedArg) -> Span { let mut serialized = core::array::ArrayTrait::new(); core::array::ArrayTrait::append(ref serialized, *self.id); + core::array::ArrayTrait::span(@serialized) } @@ -1341,6 +2720,7 @@ impl BadModelUnexpectedArgModel of dojo::model::Model { fn values(self: @BadModelUnexpectedArg) -> Span { let mut serialized = core::array::ArrayTrait::new(); core::serde::Serde::serialize(self.v, ref serialized); + core::array::ArrayTrait::span(@serialized) } @@ -1480,13 +2860,218 @@ dojo::database::introspect::Member { } } -impl BadModelNotSupportedVersionModel of dojo::model::Model { - fn entity(world: dojo::world::IWorldDispatcher, keys: Span, layout: dojo::database::introspect::Layout) -> BadModelNotSupportedVersion { +#[derive(Drop, Serde)] +pub struct BadModelNotSupportedVersionEntity { + __id: felt252, // private field + v: Vec3, + +} + +#[generate_trait] +impl BadModelNotSupportedVersionEntityImpl of BadModelNotSupportedVersionEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> BadModelNotSupportedVersionEntity { + BadModelNotSupportedVersionModelEntityImpl::get(world, entity_id) + } + + + fn get_v(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Vec3 { + let values = dojo::model::ModelEntity::::get_member( + world, + entity_id, + 578691550836206188651404750433984985630363913126316857592149308417275000080 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `BadModelNotSupportedVersion::v`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_v(self: @BadModelNotSupportedVersionEntity, world: dojo::world::IWorldDispatcher, value: Vec3) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 578691550836206188651404750433984985630363913126316857592149308417275000080, + serialized.span() + ); + } + +} + +#[generate_trait] +impl BadModelNotSupportedVersionImpl of BadModelNotSupportedVersionTrait { + fn entity_id_from_keys(id: felt252) -> felt252 { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + core::poseidon::poseidon_hash_span(serialized.span()) + } + + fn get(world: dojo::world::IWorldDispatcher, id: felt252) -> BadModelNotSupportedVersion { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + + dojo::model::Model::::get(world, serialized.span()) + } + + + fn get_v(world: dojo::world::IWorldDispatcher, id: felt252) -> Vec3 { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + + let values = dojo::model::Model::::get_member( + world, + serialized.span(), + 578691550836206188651404750433984985630363913126316857592149308417275000080 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `BadModelNotSupportedVersion::v`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_v(self: @BadModelNotSupportedVersion, world: dojo::world::IWorldDispatcher, value: Vec3) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 578691550836206188651404750433984985630363913126316857592149308417275000080, + serialized.span() + ); + } + +} + +impl BadModelNotSupportedVersionModelEntityImpl of dojo::model::ModelEntity { + fn id(self: @BadModelNotSupportedVersionEntity) -> felt252 { + *self.__id + } + + fn values(self: @BadModelNotSupportedVersionEntity) -> Span { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(self.v, ref serialized); + + core::array::ArrayTrait::span(@serialized) + } + + fn from_values(entity_id: felt252, values: Span) -> BadModelNotSupportedVersionEntity { + let mut serialized = array![entity_id]; + let mut i = 0; + loop { + if i >= values.len() { break; } + serialized.append(*values.at(i)); + i += 1; + }; + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let entity_values = core::serde::Serde::::deserialize(ref serialized); + if core::option::OptionTrait::::is_none(@entity_values) { + panic!( + "ModelEntity `BadModelNotSupportedVersionEntity`: deserialization failed." + ); + } + core::option::OptionTrait::::unwrap(entity_values) + } + + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> BadModelNotSupportedVersionEntity { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(entity_id), + dojo::model::Model::::layout() + ); + Self::from_values(entity_id, values) + } + + fn update(self: @BadModelNotSupportedVersionEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + self.values(), + dojo::model::Model::::layout() + ); + } + + fn delete(self: @BadModelNotSupportedVersionEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + dojo::model::Model::::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + entity_id: felt252, + member_id: felt252, + ) -> Span { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @BadModelNotSupportedVersionEntity, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span, + ) { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((self.id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } +} + +impl BadModelNotSupportedVersionModelImpl of dojo::model::Model { + fn get(world: dojo::world::IWorldDispatcher, keys: Span) -> BadModelNotSupportedVersion { let values = dojo::world::IWorldDispatcherTrait::entity( world, Self::selector(), - keys, - layout + dojo::world::ModelIndex::Keys(keys), + Self::layout() ); // TODO: Generate method to deserialize from keys / values directly to avoid @@ -1507,6 +3092,70 @@ impl BadModelNotSupportedVersionModel of dojo::model::Model::unwrap(entity) } + fn set( + self: @BadModelNotSupportedVersion, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::values(self), + Self::layout() + ); + } + + fn delete( + self: @BadModelNotSupportedVersion, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + keys: Span, + member_id: felt252 + ) -> Span { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + let entity_id = dojo::utils::entity_id_from_keys(keys); + dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @BadModelNotSupportedVersion, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span + ) { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((self.entity_id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + #[inline(always)] fn name() -> ByteArray { "BadModelNotSupportedVersion" @@ -1546,11 +3195,17 @@ impl BadModelNotSupportedVersionModel of dojo::model::Model felt252 { 3437408695301308226171664635441698996501144546809569617702850025816833723775 } - + + #[inline(always)] + fn entity_id(self: @BadModelNotSupportedVersion) -> felt252 { + core::poseidon::poseidon_hash_span(self.keys()) + } + #[inline(always)] fn keys(self: @BadModelNotSupportedVersion) -> Span { let mut serialized = core::array::ArrayTrait::new(); core::array::ArrayTrait::append(ref serialized, *self.id); + core::array::ArrayTrait::span(@serialized) } @@ -1558,6 +3213,7 @@ impl BadModelNotSupportedVersionModel of dojo::model::Model Span { let mut serialized = core::array::ArrayTrait::new(); core::serde::Serde::serialize(self.v, ref serialized); + core::array::ArrayTrait::span(@serialized) } @@ -1697,16 +3353,221 @@ dojo::database::introspect::Member { } } -impl Modelv0Model of dojo::model::Model { - fn entity(world: dojo::world::IWorldDispatcher, keys: Span, layout: dojo::database::introspect::Layout) -> Modelv0 { - let values = dojo::world::IWorldDispatcherTrait::entity( +#[derive(Drop, Serde)] +pub struct Modelv0Entity { + __id: felt252, // private field + v: Vec3, + +} + +#[generate_trait] +impl Modelv0EntityImpl of Modelv0EntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Modelv0Entity { + Modelv0ModelEntityImpl::get(world, entity_id) + } + + + fn get_v(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Vec3 { + let values = dojo::model::ModelEntity::::get_member( world, - Self::selector(), - keys, - layout + entity_id, + 578691550836206188651404750433984985630363913126316857592149308417275000080 ); - // TODO: Generate method to deserialize from keys / values directly to avoid + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `Modelv0::v`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_v(self: @Modelv0Entity, world: dojo::world::IWorldDispatcher, value: Vec3) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 578691550836206188651404750433984985630363913126316857592149308417275000080, + serialized.span() + ); + } + +} + +#[generate_trait] +impl Modelv0Impl of Modelv0Trait { + fn entity_id_from_keys(id: felt252) -> felt252 { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + core::poseidon::poseidon_hash_span(serialized.span()) + } + + fn get(world: dojo::world::IWorldDispatcher, id: felt252) -> Modelv0 { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + + dojo::model::Model::::get(world, serialized.span()) + } + + + fn get_v(world: dojo::world::IWorldDispatcher, id: felt252) -> Vec3 { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + + let values = dojo::model::Model::::get_member( + world, + serialized.span(), + 578691550836206188651404750433984985630363913126316857592149308417275000080 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `Modelv0::v`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_v(self: @Modelv0, world: dojo::world::IWorldDispatcher, value: Vec3) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 578691550836206188651404750433984985630363913126316857592149308417275000080, + serialized.span() + ); + } + +} + +impl Modelv0ModelEntityImpl of dojo::model::ModelEntity { + fn id(self: @Modelv0Entity) -> felt252 { + *self.__id + } + + fn values(self: @Modelv0Entity) -> Span { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(self.v, ref serialized); + + core::array::ArrayTrait::span(@serialized) + } + + fn from_values(entity_id: felt252, values: Span) -> Modelv0Entity { + let mut serialized = array![entity_id]; + let mut i = 0; + loop { + if i >= values.len() { break; } + serialized.append(*values.at(i)); + i += 1; + }; + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let entity_values = core::serde::Serde::::deserialize(ref serialized); + if core::option::OptionTrait::::is_none(@entity_values) { + panic!( + "ModelEntity `Modelv0Entity`: deserialization failed." + ); + } + core::option::OptionTrait::::unwrap(entity_values) + } + + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Modelv0Entity { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(entity_id), + dojo::model::Model::::layout() + ); + Self::from_values(entity_id, values) + } + + fn update(self: @Modelv0Entity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + self.values(), + dojo::model::Model::::layout() + ); + } + + fn delete(self: @Modelv0Entity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + dojo::model::Model::::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + entity_id: felt252, + member_id: felt252, + ) -> Span { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @Modelv0Entity, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span, + ) { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((self.id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } +} + +impl Modelv0ModelImpl of dojo::model::Model { + fn get(world: dojo::world::IWorldDispatcher, keys: Span) -> Modelv0 { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(keys), + Self::layout() + ); + + // TODO: Generate method to deserialize from keys / values directly to avoid // serializing to intermediate array. let mut serialized = core::array::ArrayTrait::new(); core::array::serialize_array_helper(keys, ref serialized); @@ -1724,6 +3585,70 @@ impl Modelv0Model of dojo::model::Model { core::option::OptionTrait::::unwrap(entity) } + fn set( + self: @Modelv0, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::values(self), + Self::layout() + ); + } + + fn delete( + self: @Modelv0, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + keys: Span, + member_id: felt252 + ) -> Span { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + let entity_id = dojo::utils::entity_id_from_keys(keys); + dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @Modelv0, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span + ) { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((self.entity_id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + #[inline(always)] fn name() -> ByteArray { "Modelv0" @@ -1763,11 +3688,17 @@ impl Modelv0Model of dojo::model::Model { fn namespace_hash() -> felt252 { 3437408695301308226171664635441698996501144546809569617702850025816833723775 } - + + #[inline(always)] + fn entity_id(self: @Modelv0) -> felt252 { + core::poseidon::poseidon_hash_span(self.keys()) + } + #[inline(always)] fn keys(self: @Modelv0) -> Span { let mut serialized = core::array::ArrayTrait::new(); core::array::ArrayTrait::append(ref serialized, *self.id); + core::array::ArrayTrait::span(@serialized) } @@ -1775,6 +3706,7 @@ impl Modelv0Model of dojo::model::Model { fn values(self: @Modelv0) -> Span { let mut serialized = core::array::ArrayTrait::new(); core::serde::Serde::serialize(self.v, ref serialized); + core::array::ArrayTrait::span(@serialized) } @@ -1914,13 +3846,218 @@ dojo::database::introspect::Member { } } -impl ModelWithBadNamespaceFormatModel of dojo::model::Model { - fn entity(world: dojo::world::IWorldDispatcher, keys: Span, layout: dojo::database::introspect::Layout) -> ModelWithBadNamespaceFormat { +#[derive(Drop, Serde)] +pub struct ModelWithBadNamespaceFormatEntity { + __id: felt252, // private field + v: Vec3, + +} + +#[generate_trait] +impl ModelWithBadNamespaceFormatEntityImpl of ModelWithBadNamespaceFormatEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> ModelWithBadNamespaceFormatEntity { + ModelWithBadNamespaceFormatModelEntityImpl::get(world, entity_id) + } + + + fn get_v(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Vec3 { + let values = dojo::model::ModelEntity::::get_member( + world, + entity_id, + 578691550836206188651404750433984985630363913126316857592149308417275000080 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `ModelWithBadNamespaceFormat::v`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_v(self: @ModelWithBadNamespaceFormatEntity, world: dojo::world::IWorldDispatcher, value: Vec3) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 578691550836206188651404750433984985630363913126316857592149308417275000080, + serialized.span() + ); + } + +} + +#[generate_trait] +impl ModelWithBadNamespaceFormatImpl of ModelWithBadNamespaceFormatTrait { + fn entity_id_from_keys(id: felt252) -> felt252 { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + core::poseidon::poseidon_hash_span(serialized.span()) + } + + fn get(world: dojo::world::IWorldDispatcher, id: felt252) -> ModelWithBadNamespaceFormat { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + + dojo::model::Model::::get(world, serialized.span()) + } + + + fn get_v(world: dojo::world::IWorldDispatcher, id: felt252) -> Vec3 { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + + let values = dojo::model::Model::::get_member( + world, + serialized.span(), + 578691550836206188651404750433984985630363913126316857592149308417275000080 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `ModelWithBadNamespaceFormat::v`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_v(self: @ModelWithBadNamespaceFormat, world: dojo::world::IWorldDispatcher, value: Vec3) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 578691550836206188651404750433984985630363913126316857592149308417275000080, + serialized.span() + ); + } + +} + +impl ModelWithBadNamespaceFormatModelEntityImpl of dojo::model::ModelEntity { + fn id(self: @ModelWithBadNamespaceFormatEntity) -> felt252 { + *self.__id + } + + fn values(self: @ModelWithBadNamespaceFormatEntity) -> Span { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(self.v, ref serialized); + + core::array::ArrayTrait::span(@serialized) + } + + fn from_values(entity_id: felt252, values: Span) -> ModelWithBadNamespaceFormatEntity { + let mut serialized = array![entity_id]; + let mut i = 0; + loop { + if i >= values.len() { break; } + serialized.append(*values.at(i)); + i += 1; + }; + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let entity_values = core::serde::Serde::::deserialize(ref serialized); + if core::option::OptionTrait::::is_none(@entity_values) { + panic!( + "ModelEntity `ModelWithBadNamespaceFormatEntity`: deserialization failed." + ); + } + core::option::OptionTrait::::unwrap(entity_values) + } + + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> ModelWithBadNamespaceFormatEntity { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(entity_id), + dojo::model::Model::::layout() + ); + Self::from_values(entity_id, values) + } + + fn update(self: @ModelWithBadNamespaceFormatEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + self.values(), + dojo::model::Model::::layout() + ); + } + + fn delete(self: @ModelWithBadNamespaceFormatEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + dojo::model::Model::::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + entity_id: felt252, + member_id: felt252, + ) -> Span { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @ModelWithBadNamespaceFormatEntity, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span, + ) { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((self.id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } +} + +impl ModelWithBadNamespaceFormatModelImpl of dojo::model::Model { + fn get(world: dojo::world::IWorldDispatcher, keys: Span) -> ModelWithBadNamespaceFormat { let values = dojo::world::IWorldDispatcherTrait::entity( world, Self::selector(), - keys, - layout + dojo::world::ModelIndex::Keys(keys), + Self::layout() ); // TODO: Generate method to deserialize from keys / values directly to avoid @@ -1941,6 +4078,70 @@ impl ModelWithBadNamespaceFormatModel of dojo::model::Model::unwrap(entity) } + fn set( + self: @ModelWithBadNamespaceFormat, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::values(self), + Self::layout() + ); + } + + fn delete( + self: @ModelWithBadNamespaceFormat, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + keys: Span, + member_id: felt252 + ) -> Span { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + let entity_id = dojo::utils::entity_id_from_keys(keys); + dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @ModelWithBadNamespaceFormat, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span + ) { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((self.entity_id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + #[inline(always)] fn name() -> ByteArray { "ModelWithBadNamespaceFormat" @@ -1980,11 +4181,17 @@ impl ModelWithBadNamespaceFormatModel of dojo::model::Model felt252 { 2518247443458975119180817677753479732439290689944304814934908400279022945373 } - + + #[inline(always)] + fn entity_id(self: @ModelWithBadNamespaceFormat) -> felt252 { + core::poseidon::poseidon_hash_span(self.keys()) + } + #[inline(always)] fn keys(self: @ModelWithBadNamespaceFormat) -> Span { let mut serialized = core::array::ArrayTrait::new(); core::array::ArrayTrait::append(ref serialized, *self.id); + core::array::ArrayTrait::span(@serialized) } @@ -1992,6 +4199,7 @@ impl ModelWithBadNamespaceFormatModel of dojo::model::Model Span { let mut serialized = core::array::ArrayTrait::new(); core::serde::Serde::serialize(self.v, ref serialized); + core::array::ArrayTrait::span(@serialized) } @@ -2131,25 +4339,230 @@ dojo::database::introspect::Member { } } -impl ModelWithShortStringNamespaceModel of dojo::model::Model { - fn entity(world: dojo::world::IWorldDispatcher, keys: Span, layout: dojo::database::introspect::Layout) -> ModelWithShortStringNamespace { - let values = dojo::world::IWorldDispatcherTrait::entity( +#[derive(Drop, Serde)] +pub struct ModelWithShortStringNamespaceEntity { + __id: felt252, // private field + v: Vec3, + +} + +#[generate_trait] +impl ModelWithShortStringNamespaceEntityImpl of ModelWithShortStringNamespaceEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> ModelWithShortStringNamespaceEntity { + ModelWithShortStringNamespaceModelEntityImpl::get(world, entity_id) + } + + + fn get_v(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Vec3 { + let values = dojo::model::ModelEntity::::get_member( world, - Self::selector(), - keys, - layout + entity_id, + 578691550836206188651404750433984985630363913126316857592149308417275000080 ); - // TODO: Generate method to deserialize from keys / values directly to avoid - // serializing to intermediate array. let mut serialized = core::array::ArrayTrait::new(); - core::array::serialize_array_helper(keys, ref serialized); core::array::serialize_array_helper(values, ref serialized); let mut serialized = core::array::ArrayTrait::span(@serialized); - let entity = core::serde::Serde::::deserialize(ref serialized); + let field_value = core::serde::Serde::::deserialize(ref serialized); - if core::option::OptionTrait::::is_none(@entity) { + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `ModelWithShortStringNamespace::v`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_v(self: @ModelWithShortStringNamespaceEntity, world: dojo::world::IWorldDispatcher, value: Vec3) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 578691550836206188651404750433984985630363913126316857592149308417275000080, + serialized.span() + ); + } + +} + +#[generate_trait] +impl ModelWithShortStringNamespaceImpl of ModelWithShortStringNamespaceTrait { + fn entity_id_from_keys(id: felt252) -> felt252 { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + core::poseidon::poseidon_hash_span(serialized.span()) + } + + fn get(world: dojo::world::IWorldDispatcher, id: felt252) -> ModelWithShortStringNamespace { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + + dojo::model::Model::::get(world, serialized.span()) + } + + + fn get_v(world: dojo::world::IWorldDispatcher, id: felt252) -> Vec3 { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + + let values = dojo::model::Model::::get_member( + world, + serialized.span(), + 578691550836206188651404750433984985630363913126316857592149308417275000080 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `ModelWithShortStringNamespace::v`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_v(self: @ModelWithShortStringNamespace, world: dojo::world::IWorldDispatcher, value: Vec3) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 578691550836206188651404750433984985630363913126316857592149308417275000080, + serialized.span() + ); + } + +} + +impl ModelWithShortStringNamespaceModelEntityImpl of dojo::model::ModelEntity { + fn id(self: @ModelWithShortStringNamespaceEntity) -> felt252 { + *self.__id + } + + fn values(self: @ModelWithShortStringNamespaceEntity) -> Span { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(self.v, ref serialized); + + core::array::ArrayTrait::span(@serialized) + } + + fn from_values(entity_id: felt252, values: Span) -> ModelWithShortStringNamespaceEntity { + let mut serialized = array![entity_id]; + let mut i = 0; + loop { + if i >= values.len() { break; } + serialized.append(*values.at(i)); + i += 1; + }; + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let entity_values = core::serde::Serde::::deserialize(ref serialized); + if core::option::OptionTrait::::is_none(@entity_values) { + panic!( + "ModelEntity `ModelWithShortStringNamespaceEntity`: deserialization failed." + ); + } + core::option::OptionTrait::::unwrap(entity_values) + } + + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> ModelWithShortStringNamespaceEntity { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(entity_id), + dojo::model::Model::::layout() + ); + Self::from_values(entity_id, values) + } + + fn update(self: @ModelWithShortStringNamespaceEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + self.values(), + dojo::model::Model::::layout() + ); + } + + fn delete(self: @ModelWithShortStringNamespaceEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + dojo::model::Model::::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + entity_id: felt252, + member_id: felt252, + ) -> Span { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @ModelWithShortStringNamespaceEntity, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span, + ) { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((self.id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } +} + +impl ModelWithShortStringNamespaceModelImpl of dojo::model::Model { + fn get(world: dojo::world::IWorldDispatcher, keys: Span) -> ModelWithShortStringNamespace { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(keys), + Self::layout() + ); + + // TODO: Generate method to deserialize from keys / values directly to avoid + // serializing to intermediate array. + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(keys, ref serialized); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let entity = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@entity) { panic!( "Model `ModelWithShortStringNamespace`: deserialization failed. Ensure the length of the keys tuple is matching the number of #[key] fields in the model struct." ); @@ -2158,6 +4571,70 @@ impl ModelWithShortStringNamespaceModel of dojo::model::Model::unwrap(entity) } + fn set( + self: @ModelWithShortStringNamespace, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::values(self), + Self::layout() + ); + } + + fn delete( + self: @ModelWithShortStringNamespace, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + keys: Span, + member_id: felt252 + ) -> Span { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + let entity_id = dojo::utils::entity_id_from_keys(keys); + dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @ModelWithShortStringNamespace, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span + ) { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((self.entity_id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + #[inline(always)] fn name() -> ByteArray { "ModelWithShortStringNamespace" @@ -2197,11 +4674,17 @@ impl ModelWithShortStringNamespaceModel of dojo::model::Model felt252 { 1685136890688416384941629523783652800960468745356230625531475538826800548713 } - + + #[inline(always)] + fn entity_id(self: @ModelWithShortStringNamespace) -> felt252 { + core::poseidon::poseidon_hash_span(self.keys()) + } + #[inline(always)] fn keys(self: @ModelWithShortStringNamespace) -> Span { let mut serialized = core::array::ArrayTrait::new(); core::array::ArrayTrait::append(ref serialized, *self.id); + core::array::ArrayTrait::span(@serialized) } @@ -2209,6 +4692,7 @@ impl ModelWithShortStringNamespaceModel of dojo::model::Model Span { let mut serialized = core::array::ArrayTrait::new(); core::serde::Serde::serialize(self.v, ref serialized); + core::array::ArrayTrait::span(@serialized) } @@ -2348,13 +4832,218 @@ dojo::database::introspect::Member { } } -impl ModelWithStringNamespaceModel of dojo::model::Model { - fn entity(world: dojo::world::IWorldDispatcher, keys: Span, layout: dojo::database::introspect::Layout) -> ModelWithStringNamespace { +#[derive(Drop, Serde)] +pub struct ModelWithStringNamespaceEntity { + __id: felt252, // private field + v: Vec3, + +} + +#[generate_trait] +impl ModelWithStringNamespaceEntityImpl of ModelWithStringNamespaceEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> ModelWithStringNamespaceEntity { + ModelWithStringNamespaceModelEntityImpl::get(world, entity_id) + } + + + fn get_v(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Vec3 { + let values = dojo::model::ModelEntity::::get_member( + world, + entity_id, + 578691550836206188651404750433984985630363913126316857592149308417275000080 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `ModelWithStringNamespace::v`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_v(self: @ModelWithStringNamespaceEntity, world: dojo::world::IWorldDispatcher, value: Vec3) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 578691550836206188651404750433984985630363913126316857592149308417275000080, + serialized.span() + ); + } + +} + +#[generate_trait] +impl ModelWithStringNamespaceImpl of ModelWithStringNamespaceTrait { + fn entity_id_from_keys(id: felt252) -> felt252 { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + core::poseidon::poseidon_hash_span(serialized.span()) + } + + fn get(world: dojo::world::IWorldDispatcher, id: felt252) -> ModelWithStringNamespace { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + + dojo::model::Model::::get(world, serialized.span()) + } + + + fn get_v(world: dojo::world::IWorldDispatcher, id: felt252) -> Vec3 { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + + let values = dojo::model::Model::::get_member( + world, + serialized.span(), + 578691550836206188651404750433984985630363913126316857592149308417275000080 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `ModelWithStringNamespace::v`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_v(self: @ModelWithStringNamespace, world: dojo::world::IWorldDispatcher, value: Vec3) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 578691550836206188651404750433984985630363913126316857592149308417275000080, + serialized.span() + ); + } + +} + +impl ModelWithStringNamespaceModelEntityImpl of dojo::model::ModelEntity { + fn id(self: @ModelWithStringNamespaceEntity) -> felt252 { + *self.__id + } + + fn values(self: @ModelWithStringNamespaceEntity) -> Span { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(self.v, ref serialized); + + core::array::ArrayTrait::span(@serialized) + } + + fn from_values(entity_id: felt252, values: Span) -> ModelWithStringNamespaceEntity { + let mut serialized = array![entity_id]; + let mut i = 0; + loop { + if i >= values.len() { break; } + serialized.append(*values.at(i)); + i += 1; + }; + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let entity_values = core::serde::Serde::::deserialize(ref serialized); + if core::option::OptionTrait::::is_none(@entity_values) { + panic!( + "ModelEntity `ModelWithStringNamespaceEntity`: deserialization failed." + ); + } + core::option::OptionTrait::::unwrap(entity_values) + } + + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> ModelWithStringNamespaceEntity { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(entity_id), + dojo::model::Model::::layout() + ); + Self::from_values(entity_id, values) + } + + fn update(self: @ModelWithStringNamespaceEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + self.values(), + dojo::model::Model::::layout() + ); + } + + fn delete(self: @ModelWithStringNamespaceEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + dojo::model::Model::::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + entity_id: felt252, + member_id: felt252, + ) -> Span { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @ModelWithStringNamespaceEntity, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span, + ) { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((self.id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } +} + +impl ModelWithStringNamespaceModelImpl of dojo::model::Model { + fn get(world: dojo::world::IWorldDispatcher, keys: Span) -> ModelWithStringNamespace { let values = dojo::world::IWorldDispatcherTrait::entity( world, Self::selector(), - keys, - layout + dojo::world::ModelIndex::Keys(keys), + Self::layout() ); // TODO: Generate method to deserialize from keys / values directly to avoid @@ -2375,6 +5064,70 @@ impl ModelWithStringNamespaceModel of dojo::model::Model::unwrap(entity) } + fn set( + self: @ModelWithStringNamespace, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::values(self), + Self::layout() + ); + } + + fn delete( + self: @ModelWithStringNamespace, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + keys: Span, + member_id: felt252 + ) -> Span { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + let entity_id = dojo::utils::entity_id_from_keys(keys); + dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @ModelWithStringNamespace, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span + ) { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((self.entity_id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + #[inline(always)] fn name() -> ByteArray { "ModelWithStringNamespace" @@ -2414,11 +5167,17 @@ impl ModelWithStringNamespaceModel of dojo::model::Model felt252 { 1685136890688416384941629523783652800960468745356230625531475538826800548713 } - + + #[inline(always)] + fn entity_id(self: @ModelWithStringNamespace) -> felt252 { + core::poseidon::poseidon_hash_span(self.keys()) + } + #[inline(always)] fn keys(self: @ModelWithStringNamespace) -> Span { let mut serialized = core::array::ArrayTrait::new(); core::array::ArrayTrait::append(ref serialized, *self.id); + core::array::ArrayTrait::span(@serialized) } @@ -2426,6 +5185,7 @@ impl ModelWithStringNamespaceModel of dojo::model::Model Span { let mut serialized = core::array::ArrayTrait::new(); core::serde::Serde::serialize(self.v, ref serialized); + core::array::ArrayTrait::span(@serialized) } @@ -2565,16 +5325,221 @@ dojo::database::introspect::Member { } } -impl PositionModel of dojo::model::Model { - fn entity(world: dojo::world::IWorldDispatcher, keys: Span, layout: dojo::database::introspect::Layout) -> Position { - let values = dojo::world::IWorldDispatcherTrait::entity( +#[derive(Drop, Serde)] +pub struct PositionEntity { + __id: felt252, // private field + v: Vec3, + +} + +#[generate_trait] +impl PositionEntityImpl of PositionEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> PositionEntity { + PositionModelEntityImpl::get(world, entity_id) + } + + + fn get_v(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Vec3 { + let values = dojo::model::ModelEntity::::get_member( world, - Self::selector(), - keys, - layout + entity_id, + 578691550836206188651404750433984985630363913126316857592149308417275000080 ); - // TODO: Generate method to deserialize from keys / values directly to avoid + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `Position::v`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_v(self: @PositionEntity, world: dojo::world::IWorldDispatcher, value: Vec3) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 578691550836206188651404750433984985630363913126316857592149308417275000080, + serialized.span() + ); + } + +} + +#[generate_trait] +impl PositionImpl of PositionTrait { + fn entity_id_from_keys(id: felt252) -> felt252 { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + core::poseidon::poseidon_hash_span(serialized.span()) + } + + fn get(world: dojo::world::IWorldDispatcher, id: felt252) -> Position { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + + dojo::model::Model::::get(world, serialized.span()) + } + + + fn get_v(world: dojo::world::IWorldDispatcher, id: felt252) -> Vec3 { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + + let values = dojo::model::Model::::get_member( + world, + serialized.span(), + 578691550836206188651404750433984985630363913126316857592149308417275000080 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `Position::v`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_v(self: @Position, world: dojo::world::IWorldDispatcher, value: Vec3) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 578691550836206188651404750433984985630363913126316857592149308417275000080, + serialized.span() + ); + } + +} + +impl PositionModelEntityImpl of dojo::model::ModelEntity { + fn id(self: @PositionEntity) -> felt252 { + *self.__id + } + + fn values(self: @PositionEntity) -> Span { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(self.v, ref serialized); + + core::array::ArrayTrait::span(@serialized) + } + + fn from_values(entity_id: felt252, values: Span) -> PositionEntity { + let mut serialized = array![entity_id]; + let mut i = 0; + loop { + if i >= values.len() { break; } + serialized.append(*values.at(i)); + i += 1; + }; + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let entity_values = core::serde::Serde::::deserialize(ref serialized); + if core::option::OptionTrait::::is_none(@entity_values) { + panic!( + "ModelEntity `PositionEntity`: deserialization failed." + ); + } + core::option::OptionTrait::::unwrap(entity_values) + } + + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> PositionEntity { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(entity_id), + dojo::model::Model::::layout() + ); + Self::from_values(entity_id, values) + } + + fn update(self: @PositionEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + self.values(), + dojo::model::Model::::layout() + ); + } + + fn delete(self: @PositionEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + dojo::model::Model::::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + entity_id: felt252, + member_id: felt252, + ) -> Span { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @PositionEntity, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span, + ) { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((self.id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } +} + +impl PositionModelImpl of dojo::model::Model { + fn get(world: dojo::world::IWorldDispatcher, keys: Span) -> Position { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(keys), + Self::layout() + ); + + // TODO: Generate method to deserialize from keys / values directly to avoid // serializing to intermediate array. let mut serialized = core::array::ArrayTrait::new(); core::array::serialize_array_helper(keys, ref serialized); @@ -2592,6 +5557,70 @@ impl PositionModel of dojo::model::Model { core::option::OptionTrait::::unwrap(entity) } + fn set( + self: @Position, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::values(self), + Self::layout() + ); + } + + fn delete( + self: @Position, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + keys: Span, + member_id: felt252 + ) -> Span { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + let entity_id = dojo::utils::entity_id_from_keys(keys); + dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @Position, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span + ) { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((self.entity_id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + #[inline(always)] fn name() -> ByteArray { "Position" @@ -2631,11 +5660,17 @@ impl PositionModel of dojo::model::Model { fn namespace_hash() -> felt252 { 3437408695301308226171664635441698996501144546809569617702850025816833723775 } - + + #[inline(always)] + fn entity_id(self: @Position) -> felt252 { + core::poseidon::poseidon_hash_span(self.keys()) + } + #[inline(always)] fn keys(self: @Position) -> Span { let mut serialized = core::array::ArrayTrait::new(); core::array::ArrayTrait::append(ref serialized, *self.id); + core::array::ArrayTrait::span(@serialized) } @@ -2643,6 +5678,7 @@ impl PositionModel of dojo::model::Model { fn values(self: @Position) -> Span { let mut serialized = core::array::ArrayTrait::new(); core::serde::Serde::serialize(self.v, ref serialized); + core::array::ArrayTrait::span(@serialized) } @@ -2782,13 +5818,215 @@ impl RolesIntrospect<> of dojo::database::introspect::Introspect> { } } -impl RolesModel of dojo::model::Model { - fn entity(world: dojo::world::IWorldDispatcher, keys: Span, layout: dojo::database::introspect::Layout) -> Roles { +#[derive(Drop, Serde)] +pub struct RolesEntity { + __id: felt252, // private field + role_ids: Array, + +} + +#[generate_trait] +impl RolesEntityImpl of RolesEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> RolesEntity { + RolesModelEntityImpl::get(world, entity_id) + } + + + fn get_role_ids(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Array { + let values = dojo::model::ModelEntity::::get_member( + world, + entity_id, + 387776731289756409274549987067854286905927440612427426920343953432870065647 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::>::deserialize(ref serialized); + + if core::option::OptionTrait::>::is_none(@field_value) { + panic!( + "Field `Roles::role_ids`: deserialization failed." + ); + } + + core::option::OptionTrait::>::unwrap(field_value) + } + + fn set_role_ids(self: @RolesEntity, world: dojo::world::IWorldDispatcher, value: Array) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 387776731289756409274549987067854286905927440612427426920343953432870065647, + serialized.span() + ); + } + +} + +#[generate_trait] +impl RolesImpl of RolesTrait { + fn entity_id_from_keys() -> felt252 { + let mut serialized = core::array::ArrayTrait::new(); + + core::poseidon::poseidon_hash_span(serialized.span()) + } + + fn get(world: dojo::world::IWorldDispatcher, ) -> Roles { + let mut serialized = core::array::ArrayTrait::new(); + + + dojo::model::Model::::get(world, serialized.span()) + } + + + fn get_role_ids(world: dojo::world::IWorldDispatcher, ) -> Array { + let mut serialized = core::array::ArrayTrait::new(); + + + let values = dojo::model::Model::::get_member( + world, + serialized.span(), + 387776731289756409274549987067854286905927440612427426920343953432870065647 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::>::deserialize(ref serialized); + + if core::option::OptionTrait::>::is_none(@field_value) { + panic!( + "Field `Roles::role_ids`: deserialization failed." + ); + } + + core::option::OptionTrait::>::unwrap(field_value) + } + + fn set_role_ids(self: @Roles, world: dojo::world::IWorldDispatcher, value: Array) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 387776731289756409274549987067854286905927440612427426920343953432870065647, + serialized.span() + ); + } + +} + +impl RolesModelEntityImpl of dojo::model::ModelEntity { + fn id(self: @RolesEntity) -> felt252 { + *self.__id + } + + fn values(self: @RolesEntity) -> Span { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(self.role_ids, ref serialized); + + core::array::ArrayTrait::span(@serialized) + } + + fn from_values(entity_id: felt252, values: Span) -> RolesEntity { + let mut serialized = array![entity_id]; + let mut i = 0; + loop { + if i >= values.len() { break; } + serialized.append(*values.at(i)); + i += 1; + }; + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let entity_values = core::serde::Serde::::deserialize(ref serialized); + if core::option::OptionTrait::::is_none(@entity_values) { + panic!( + "ModelEntity `RolesEntity`: deserialization failed." + ); + } + core::option::OptionTrait::::unwrap(entity_values) + } + + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> RolesEntity { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(entity_id), + dojo::model::Model::::layout() + ); + Self::from_values(entity_id, values) + } + + fn update(self: @RolesEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + self.values(), + dojo::model::Model::::layout() + ); + } + + fn delete(self: @RolesEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + dojo::model::Model::::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + entity_id: felt252, + member_id: felt252, + ) -> Span { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @RolesEntity, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span, + ) { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((self.id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } +} + +impl RolesModelImpl of dojo::model::Model { + fn get(world: dojo::world::IWorldDispatcher, keys: Span) -> Roles { let values = dojo::world::IWorldDispatcherTrait::entity( world, Self::selector(), - keys, - layout + dojo::world::ModelIndex::Keys(keys), + Self::layout() ); // TODO: Generate method to deserialize from keys / values directly to avoid @@ -2809,6 +6047,70 @@ impl RolesModel of dojo::model::Model { core::option::OptionTrait::::unwrap(entity) } + fn set( + self: @Roles, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::values(self), + Self::layout() + ); + } + + fn delete( + self: @Roles, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + keys: Span, + member_id: felt252 + ) -> Span { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + let entity_id = dojo::utils::entity_id_from_keys(keys); + dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @Roles, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span + ) { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((self.entity_id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + #[inline(always)] fn name() -> ByteArray { "Roles" @@ -2848,7 +6150,12 @@ impl RolesModel of dojo::model::Model { fn namespace_hash() -> felt252 { 3437408695301308226171664635441698996501144546809569617702850025816833723775 } - + + #[inline(always)] + fn entity_id(self: @Roles) -> felt252 { + core::poseidon::poseidon_hash_span(self.keys()) + } + #[inline(always)] fn keys(self: @Roles) -> Span { let mut serialized = core::array::ArrayTrait::new(); @@ -2860,6 +6167,7 @@ impl RolesModel of dojo::model::Model { fn values(self: @Roles) -> Span { let mut serialized = core::array::ArrayTrait::new(); core::serde::Serde::serialize(self.role_ids, ref serialized); + core::array::ArrayTrait::span(@serialized) } @@ -2991,23 +6299,156 @@ impl OnlyKeyModelIntrospect<> of dojo::database::introspect::Introspect { - fn entity(world: dojo::world::IWorldDispatcher, keys: Span, layout: dojo::database::introspect::Layout) -> OnlyKeyModel { - let values = dojo::world::IWorldDispatcherTrait::entity( - world, - Self::selector(), - keys, - layout - ); +#[derive(Drop, Serde)] +pub struct OnlyKeyModelEntity { + __id: felt252, // private field + +} - // TODO: Generate method to deserialize from keys / values directly to avoid - // serializing to intermediate array. - let mut serialized = core::array::ArrayTrait::new(); - core::array::serialize_array_helper(keys, ref serialized); - core::array::serialize_array_helper(values, ref serialized); - let mut serialized = core::array::ArrayTrait::span(@serialized); +#[generate_trait] +impl OnlyKeyModelEntityImpl of OnlyKeyModelEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> OnlyKeyModelEntity { + OnlyKeyModelModelEntityImpl::get(world, entity_id) + } - let entity = core::serde::Serde::::deserialize(ref serialized); + +} + +#[generate_trait] +impl OnlyKeyModelImpl of OnlyKeyModelTrait { + fn entity_id_from_keys(id: felt252) -> felt252 { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + core::poseidon::poseidon_hash_span(serialized.span()) + } + + fn get(world: dojo::world::IWorldDispatcher, id: felt252) -> OnlyKeyModel { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, id); + + + dojo::model::Model::::get(world, serialized.span()) + } + + +} + +impl OnlyKeyModelModelEntityImpl of dojo::model::ModelEntity { + fn id(self: @OnlyKeyModelEntity) -> felt252 { + *self.__id + } + + fn values(self: @OnlyKeyModelEntity) -> Span { + let mut serialized = core::array::ArrayTrait::new(); + + core::array::ArrayTrait::span(@serialized) + } + + fn from_values(entity_id: felt252, values: Span) -> OnlyKeyModelEntity { + let mut serialized = array![entity_id]; + let mut i = 0; + loop { + if i >= values.len() { break; } + serialized.append(*values.at(i)); + i += 1; + }; + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let entity_values = core::serde::Serde::::deserialize(ref serialized); + if core::option::OptionTrait::::is_none(@entity_values) { + panic!( + "ModelEntity `OnlyKeyModelEntity`: deserialization failed." + ); + } + core::option::OptionTrait::::unwrap(entity_values) + } + + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> OnlyKeyModelEntity { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(entity_id), + dojo::model::Model::::layout() + ); + Self::from_values(entity_id, values) + } + + fn update(self: @OnlyKeyModelEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + self.values(), + dojo::model::Model::::layout() + ); + } + + fn delete(self: @OnlyKeyModelEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + dojo::model::Model::::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + entity_id: felt252, + member_id: felt252, + ) -> Span { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @OnlyKeyModelEntity, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span, + ) { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((self.id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } +} + +impl OnlyKeyModelModelImpl of dojo::model::Model { + fn get(world: dojo::world::IWorldDispatcher, keys: Span) -> OnlyKeyModel { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(keys), + Self::layout() + ); + + // TODO: Generate method to deserialize from keys / values directly to avoid + // serializing to intermediate array. + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(keys, ref serialized); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let entity = core::serde::Serde::::deserialize(ref serialized); if core::option::OptionTrait::::is_none(@entity) { panic!( @@ -3018,6 +6459,70 @@ impl OnlyKeyModelModel of dojo::model::Model { core::option::OptionTrait::::unwrap(entity) } + fn set( + self: @OnlyKeyModel, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::values(self), + Self::layout() + ); + } + + fn delete( + self: @OnlyKeyModel, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + keys: Span, + member_id: felt252 + ) -> Span { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + let entity_id = dojo::utils::entity_id_from_keys(keys); + dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @OnlyKeyModel, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span + ) { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((self.entity_id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + #[inline(always)] fn name() -> ByteArray { "OnlyKeyModel" @@ -3057,11 +6562,17 @@ impl OnlyKeyModelModel of dojo::model::Model { fn namespace_hash() -> felt252 { 3437408695301308226171664635441698996501144546809569617702850025816833723775 } - + + #[inline(always)] + fn entity_id(self: @OnlyKeyModel) -> felt252 { + core::poseidon::poseidon_hash_span(self.keys()) + } + #[inline(always)] fn keys(self: @OnlyKeyModel) -> Span { let mut serialized = core::array::ArrayTrait::new(); core::array::ArrayTrait::append(ref serialized, *self.id); + core::array::ArrayTrait::span(@serialized) } @@ -3200,13 +6711,146 @@ impl U256KeyModelIntrospect<> of dojo::database::introspect::Introspect { - fn entity(world: dojo::world::IWorldDispatcher, keys: Span, layout: dojo::database::introspect::Layout) -> U256KeyModel { +#[derive(Drop, Serde)] +pub struct U256KeyModelEntity { + __id: felt252, // private field + +} + +#[generate_trait] +impl U256KeyModelEntityImpl of U256KeyModelEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> U256KeyModelEntity { + U256KeyModelModelEntityImpl::get(world, entity_id) + } + + +} + +#[generate_trait] +impl U256KeyModelImpl of U256KeyModelTrait { + fn entity_id_from_keys(id: u256) -> felt252 { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@id, ref serialized); + + core::poseidon::poseidon_hash_span(serialized.span()) + } + + fn get(world: dojo::world::IWorldDispatcher, id: u256) -> U256KeyModel { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@id, ref serialized); + + + dojo::model::Model::::get(world, serialized.span()) + } + + +} + +impl U256KeyModelModelEntityImpl of dojo::model::ModelEntity { + fn id(self: @U256KeyModelEntity) -> felt252 { + *self.__id + } + + fn values(self: @U256KeyModelEntity) -> Span { + let mut serialized = core::array::ArrayTrait::new(); + + core::array::ArrayTrait::span(@serialized) + } + + fn from_values(entity_id: felt252, values: Span) -> U256KeyModelEntity { + let mut serialized = array![entity_id]; + let mut i = 0; + loop { + if i >= values.len() { break; } + serialized.append(*values.at(i)); + i += 1; + }; + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let entity_values = core::serde::Serde::::deserialize(ref serialized); + if core::option::OptionTrait::::is_none(@entity_values) { + panic!( + "ModelEntity `U256KeyModelEntity`: deserialization failed." + ); + } + core::option::OptionTrait::::unwrap(entity_values) + } + + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> U256KeyModelEntity { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(entity_id), + dojo::model::Model::::layout() + ); + Self::from_values(entity_id, values) + } + + fn update(self: @U256KeyModelEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + self.values(), + dojo::model::Model::::layout() + ); + } + + fn delete(self: @U256KeyModelEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + dojo::model::Model::::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + entity_id: felt252, + member_id: felt252, + ) -> Span { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @U256KeyModelEntity, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span, + ) { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((self.id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } +} + +impl U256KeyModelModelImpl of dojo::model::Model { + fn get(world: dojo::world::IWorldDispatcher, keys: Span) -> U256KeyModel { let values = dojo::world::IWorldDispatcherTrait::entity( world, Self::selector(), - keys, - layout + dojo::world::ModelIndex::Keys(keys), + Self::layout() ); // TODO: Generate method to deserialize from keys / values directly to avoid @@ -3227,6 +6871,70 @@ impl U256KeyModelModel of dojo::model::Model { core::option::OptionTrait::::unwrap(entity) } + fn set( + self: @U256KeyModel, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::values(self), + Self::layout() + ); + } + + fn delete( + self: @U256KeyModel, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + keys: Span, + member_id: felt252 + ) -> Span { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + let entity_id = dojo::utils::entity_id_from_keys(keys); + dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @U256KeyModel, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span + ) { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((self.entity_id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + #[inline(always)] fn name() -> ByteArray { "U256KeyModel" @@ -3266,11 +6974,17 @@ impl U256KeyModelModel of dojo::model::Model { fn namespace_hash() -> felt252 { 3437408695301308226171664635441698996501144546809569617702850025816833723775 } - + + #[inline(always)] + fn entity_id(self: @U256KeyModel) -> felt252 { + core::poseidon::poseidon_hash_span(self.keys()) + } + #[inline(always)] fn keys(self: @U256KeyModel) -> Span { let mut serialized = core::array::ArrayTrait::new(); core::serde::Serde::serialize(self.id, ref serialized); + core::array::ArrayTrait::span(@serialized) } @@ -3422,244 +7136,221 @@ dojo::database::introspect::Member { } } -impl PlayerModel of dojo::model::Model { - fn entity(world: dojo::world::IWorldDispatcher, keys: Span, layout: dojo::database::introspect::Layout) -> Player { - let values = dojo::world::IWorldDispatcherTrait::entity( +#[derive(Drop, Serde)] +pub struct PlayerEntity { + __id: felt252, // private field + name: felt252, + +} + +#[generate_trait] +impl PlayerEntityImpl of PlayerEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> PlayerEntity { + PlayerModelEntityImpl::get(world, entity_id) + } + + + fn get_name(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> felt252 { + let values = dojo::model::ModelEntity::::get_member( world, - Self::selector(), - keys, - layout + entity_id, + 1528802474226268325865027367859591458315299653151958663884057507666229546336 ); - // TODO: Generate method to deserialize from keys / values directly to avoid - // serializing to intermediate array. let mut serialized = core::array::ArrayTrait::new(); - core::array::serialize_array_helper(keys, ref serialized); core::array::serialize_array_helper(values, ref serialized); let mut serialized = core::array::ArrayTrait::span(@serialized); - let entity = core::serde::Serde::::deserialize(ref serialized); + let field_value = core::serde::Serde::::deserialize(ref serialized); - if core::option::OptionTrait::::is_none(@entity) { + if core::option::OptionTrait::::is_none(@field_value) { panic!( - "Model `Player`: deserialization failed. Ensure the length of the keys tuple is matching the number of #[key] fields in the model struct." + "Field `Player::name`: deserialization failed." ); } - core::option::OptionTrait::::unwrap(entity) + core::option::OptionTrait::::unwrap(field_value) } - #[inline(always)] - fn name() -> ByteArray { - "Player" - } + fn set_name(self: @PlayerEntity, world: dojo::world::IWorldDispatcher, value: felt252) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); - #[inline(always)] - fn namespace() -> ByteArray { - "dojo_plugin" + self.set_member( + world, + 1528802474226268325865027367859591458315299653151958663884057507666229546336, + serialized.span() + ); } - #[inline(always)] - fn tag() -> ByteArray { - "dojo_plugin-Player" - } +} - #[inline(always)] - fn version() -> u8 { - 1 - } +#[generate_trait] +impl PlayerImpl of PlayerTrait { + fn entity_id_from_keys(game: felt252, player: ContractAddress) -> felt252 { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, game); +core::serde::Serde::serialize(@player, ref serialized); - #[inline(always)] - fn selector() -> felt252 { - 3236595220905041720254406300307550499454912078227837571413280031443759061272 + core::poseidon::poseidon_hash_span(serialized.span()) } - #[inline(always)] - fn instance_selector(self: @Player) -> felt252 { - Self::selector() - } + fn get(world: dojo::world::IWorldDispatcher, game: felt252, player: ContractAddress) -> Player { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, game); +core::serde::Serde::serialize(@player, ref serialized); - #[inline(always)] - fn name_hash() -> felt252 { - 1073075359926275415180704315933677548333097210683379121732618306925003101845 - } - #[inline(always)] - fn namespace_hash() -> felt252 { - 3437408695301308226171664635441698996501144546809569617702850025816833723775 + dojo::model::Model::::get(world, serialized.span()) } + - #[inline(always)] - fn keys(self: @Player) -> Span { + fn get_name(world: dojo::world::IWorldDispatcher, game: felt252, player: ContractAddress) -> felt252 { let mut serialized = core::array::ArrayTrait::new(); - core::array::ArrayTrait::append(ref serialized, *self.game);core::serde::Serde::serialize(self.player, ref serialized); - core::array::ArrayTrait::span(@serialized) - } + core::array::ArrayTrait::append(ref serialized, game); +core::serde::Serde::serialize(@player, ref serialized); + + + let values = dojo::model::Model::::get_member( + world, + serialized.span(), + 1528802474226268325865027367859591458315299653151958663884057507666229546336 + ); - #[inline(always)] - fn values(self: @Player) -> Span { let mut serialized = core::array::ArrayTrait::new(); - core::array::ArrayTrait::append(ref serialized, *self.name); - core::array::ArrayTrait::span(@serialized) - } + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); - #[inline(always)] - fn layout() -> dojo::database::introspect::Layout { - dojo::database::introspect::Introspect::::layout() - } + let field_value = core::serde::Serde::::deserialize(ref serialized); - #[inline(always)] - fn instance_layout(self: @Player) -> dojo::database::introspect::Layout { - Self::layout() + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `Player::name`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) } - #[inline(always)] - fn packed_size() -> Option { - let layout = Self::layout(); + fn set_name(self: @Player, world: dojo::world::IWorldDispatcher, value: felt252) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); - match layout { - dojo::database::introspect::Layout::Fixed(layout) => { - let mut span_layout = layout; - Option::Some(dojo::packing::calculate_packed_size(ref span_layout)) - }, - dojo::database::introspect::Layout::Struct(_) => Option::None, - dojo::database::introspect::Layout::Array(_) => Option::None, - dojo::database::introspect::Layout::Tuple(_) => Option::None, - dojo::database::introspect::Layout::Enum(_) => Option::None, - dojo::database::introspect::Layout::ByteArray => Option::None, - } + self.set_member( + world, + 1528802474226268325865027367859591458315299653151958663884057507666229546336, + serialized.span() + ); } + } -#[starknet::interface] -trait Iplayer { - fn ensure_abi(self: @T, model: Player); -} - -#[starknet::contract] -mod player { - use super::Player; - use super::Iplayer; - - #[storage] - struct Storage {} - - #[abi(embed_v0)] - impl DojoModelImpl of dojo::model::IModel{ - fn name(self: @ContractState) -> ByteArray { - dojo::model::Model::::name() - } - - fn namespace(self: @ContractState) -> ByteArray { - dojo::model::Model::::namespace() - } - - fn tag(self: @ContractState) -> ByteArray { - dojo::model::Model::::tag() - } - - fn version(self: @ContractState) -> u8 { - dojo::model::Model::::version() - } - - fn selector(self: @ContractState) -> felt252 { - dojo::model::Model::::selector() - } - - fn name_hash(self: @ContractState) -> felt252 { - dojo::model::Model::::name_hash() - } - - fn namespace_hash(self: @ContractState) -> felt252 { - dojo::model::Model::::namespace_hash() - } +impl PlayerModelEntityImpl of dojo::model::ModelEntity { + fn id(self: @PlayerEntity) -> felt252 { + *self.__id + } - fn unpacked_size(self: @ContractState) -> Option { - dojo::database::introspect::Introspect::::size() - } + fn values(self: @PlayerEntity) -> Span { + let mut serialized = core::array::ArrayTrait::new(); + core::array::ArrayTrait::append(ref serialized, *self.name); - fn packed_size(self: @ContractState) -> Option { - dojo::model::Model::::packed_size() - } + core::array::ArrayTrait::span(@serialized) + } - fn layout(self: @ContractState) -> dojo::database::introspect::Layout { - dojo::model::Model::::layout() - } + fn from_values(entity_id: felt252, values: Span) -> PlayerEntity { + let mut serialized = array![entity_id]; + let mut i = 0; + loop { + if i >= values.len() { break; } + serialized.append(*values.at(i)); + i += 1; + }; + let mut serialized = core::array::ArrayTrait::span(@serialized); - fn schema(self: @ContractState) -> dojo::database::introspect::Ty { - dojo::database::introspect::Introspect::::ty() + let entity_values = core::serde::Serde::::deserialize(ref serialized); + if core::option::OptionTrait::::is_none(@entity_values) { + panic!( + "ModelEntity `PlayerEntity`: deserialization failed." + ); } + core::option::OptionTrait::::unwrap(entity_values) } - #[abi(embed_v0)] - impl playerImpl of Iplayer{ - fn ensure_abi(self: @ContractState, model: Player) { - } + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> PlayerEntity { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(entity_id), + dojo::model::Model::::layout() + ); + Self::from_values(entity_id, values) } -} -impl ModelWithSimpleArrayIntrospect<> of dojo::database::introspect::Introspect> { - #[inline(always)] - fn size() -> Option { - Option::None + fn update(self: @PlayerEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + self.values(), + dojo::model::Model::::layout() + ); } - fn layout() -> dojo::database::introspect::Layout { - dojo::database::introspect::Layout::Struct( - array![ - dojo::database::introspect::FieldLayout { - selector: 512066735765477566404754172672287371265995314501343422459174036873487219331, - layout: dojo::database::introspect::Introspect::::layout() - }, -dojo::database::introspect::FieldLayout { - selector: 1591024729085637502504777720563487898377940395575083379770417352976841400819, - layout: dojo::database::introspect::Introspect:: ->::layout() - } - ].span() - ) + fn delete(self: @PlayerEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + dojo::model::Model::::layout() + ); } - #[inline(always)] - fn ty() -> dojo::database::introspect::Ty { - dojo::database::introspect::Ty::Struct( - dojo::database::introspect::Struct { - name: 'ModelWithSimpleArray', - attrs: array![].span(), - children: array![ - dojo::database::introspect::Member { - name: 'player', - attrs: array!['key'].span(), - ty: dojo::database::introspect::Introspect::::ty() - }, -dojo::database::introspect::Member { - name: 'x', - attrs: array![].span(), - ty: dojo::database::introspect::Introspect::::ty() - }, -dojo::database::introspect::Member { - name: 'y', - attrs: array![].span(), - ty: dojo::database::introspect::Ty::Array( - array![ - dojo::database::introspect::Introspect::::ty() - ].span() - ) + fn get_member( + world: dojo::world::IWorldDispatcher, + entity_id: felt252, + member_id: felt252, + ) -> Span { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @PlayerEntity, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span, + ) { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((self.id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') } - - ].span() - } - ) } } - -impl ModelWithSimpleArrayModel of dojo::model::Model { - fn entity(world: dojo::world::IWorldDispatcher, keys: Span, layout: dojo::database::introspect::Layout) -> ModelWithSimpleArray { + +impl PlayerModelImpl of dojo::model::Model { + fn get(world: dojo::world::IWorldDispatcher, keys: Span) -> Player { let values = dojo::world::IWorldDispatcherTrait::entity( world, Self::selector(), - keys, - layout + dojo::world::ModelIndex::Keys(keys), + Self::layout() ); // TODO: Generate method to deserialize from keys / values directly to avoid @@ -3669,20 +7360,84 @@ impl ModelWithSimpleArrayModel of dojo::model::Model { core::array::serialize_array_helper(values, ref serialized); let mut serialized = core::array::ArrayTrait::span(@serialized); - let entity = core::serde::Serde::::deserialize(ref serialized); + let entity = core::serde::Serde::::deserialize(ref serialized); - if core::option::OptionTrait::::is_none(@entity) { + if core::option::OptionTrait::::is_none(@entity) { panic!( - "Model `ModelWithSimpleArray`: deserialization failed. Ensure the length of the keys tuple is matching the number of #[key] fields in the model struct." + "Model `Player`: deserialization failed. Ensure the length of the keys tuple is matching the number of #[key] fields in the model struct." ); } - core::option::OptionTrait::::unwrap(entity) + core::option::OptionTrait::::unwrap(entity) + } + + fn set( + self: @Player, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::values(self), + Self::layout() + ); + } + + fn delete( + self: @Player, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + keys: Span, + member_id: felt252 + ) -> Span { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + let entity_id = dojo::utils::entity_id_from_keys(keys); + dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @Player, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span + ) { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((self.entity_id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } } #[inline(always)] fn name() -> ByteArray { - "ModelWithSimpleArray" + "Player" } #[inline(always)] @@ -3692,7 +7447,7 @@ impl ModelWithSimpleArrayModel of dojo::model::Model { #[inline(always)] fn tag() -> ByteArray { - "dojo_plugin-ModelWithSimpleArray" + "dojo_plugin-Player" } #[inline(always)] @@ -3702,45 +7457,53 @@ impl ModelWithSimpleArrayModel of dojo::model::Model { #[inline(always)] fn selector() -> felt252 { - 3015573168128997707047545520976347917082964620628387533056114714397499472255 + 3236595220905041720254406300307550499454912078227837571413280031443759061272 } #[inline(always)] - fn instance_selector(self: @ModelWithSimpleArray) -> felt252 { + fn instance_selector(self: @Player) -> felt252 { Self::selector() } #[inline(always)] fn name_hash() -> felt252 { - 173141902001925402715103859951360389436088950156916962046507357841237663931 + 1073075359926275415180704315933677548333097210683379121732618306925003101845 } #[inline(always)] fn namespace_hash() -> felt252 { 3437408695301308226171664635441698996501144546809569617702850025816833723775 } - + #[inline(always)] - fn keys(self: @ModelWithSimpleArray) -> Span { + fn entity_id(self: @Player) -> felt252 { + core::poseidon::poseidon_hash_span(self.keys()) + } + + #[inline(always)] + fn keys(self: @Player) -> Span { let mut serialized = core::array::ArrayTrait::new(); - core::serde::Serde::serialize(self.player, ref serialized); + core::array::ArrayTrait::append(ref serialized, *self.game); +core::serde::Serde::serialize(self.player, ref serialized); + core::array::ArrayTrait::span(@serialized) } #[inline(always)] - fn values(self: @ModelWithSimpleArray) -> Span { + fn values(self: @Player) -> Span { let mut serialized = core::array::ArrayTrait::new(); - core::serde::Serde::serialize(self.x, ref serialized);core::serde::Serde::serialize(self.y, ref serialized); + core::array::ArrayTrait::append(ref serialized, *self.name); + core::array::ArrayTrait::span(@serialized) } #[inline(always)] fn layout() -> dojo::database::introspect::Layout { - dojo::database::introspect::Introspect::::layout() + dojo::database::introspect::Introspect::::layout() } #[inline(always)] - fn instance_layout(self: @ModelWithSimpleArray) -> dojo::database::introspect::Layout { + fn instance_layout(self: @Player) -> dojo::database::introspect::Layout { Self::layout() } @@ -3763,14 +7526,14 @@ impl ModelWithSimpleArrayModel of dojo::model::Model { } #[starknet::interface] -trait Imodel_with_simple_array { - fn ensure_abi(self: @T, model: ModelWithSimpleArray); +trait Iplayer { + fn ensure_abi(self: @T, model: Player); } #[starknet::contract] -mod model_with_simple_array { - use super::ModelWithSimpleArray; - use super::Imodel_with_simple_array; +mod player { + use super::Player; + use super::Iplayer; #[storage] struct Storage {} @@ -3778,58 +7541,58 @@ mod model_with_simple_array { #[abi(embed_v0)] impl DojoModelImpl of dojo::model::IModel{ fn name(self: @ContractState) -> ByteArray { - dojo::model::Model::::name() + dojo::model::Model::::name() } fn namespace(self: @ContractState) -> ByteArray { - dojo::model::Model::::namespace() + dojo::model::Model::::namespace() } fn tag(self: @ContractState) -> ByteArray { - dojo::model::Model::::tag() + dojo::model::Model::::tag() } fn version(self: @ContractState) -> u8 { - dojo::model::Model::::version() + dojo::model::Model::::version() } fn selector(self: @ContractState) -> felt252 { - dojo::model::Model::::selector() + dojo::model::Model::::selector() } fn name_hash(self: @ContractState) -> felt252 { - dojo::model::Model::::name_hash() + dojo::model::Model::::name_hash() } fn namespace_hash(self: @ContractState) -> felt252 { - dojo::model::Model::::namespace_hash() + dojo::model::Model::::namespace_hash() } fn unpacked_size(self: @ContractState) -> Option { - dojo::database::introspect::Introspect::::size() + dojo::database::introspect::Introspect::::size() } fn packed_size(self: @ContractState) -> Option { - dojo::model::Model::::packed_size() + dojo::model::Model::::packed_size() } fn layout(self: @ContractState) -> dojo::database::introspect::Layout { - dojo::model::Model::::layout() + dojo::model::Model::::layout() } fn schema(self: @ContractState) -> dojo::database::introspect::Ty { - dojo::database::introspect::Introspect::::ty() + dojo::database::introspect::Introspect::::ty() } } #[abi(embed_v0)] - impl model_with_simple_arrayImpl of Imodel_with_simple_array{ - fn ensure_abi(self: @ContractState, model: ModelWithSimpleArray) { + impl playerImpl of Iplayer{ + fn ensure_abi(self: @ContractState, model: Player) { } } } -impl ModelWithByteArrayIntrospect<> of dojo::database::introspect::Introspect> { +impl ModelWithSimpleArrayIntrospect<> of dojo::database::introspect::Introspect> { #[inline(always)] fn size() -> Option { Option::None @@ -3844,7 +7607,7 @@ impl ModelWithByteArrayIntrospect<> of dojo::database::introspect::Introspect >::layout() } ].span() @@ -3855,7 +7618,7 @@ dojo::database::introspect::FieldLayout { fn ty() -> dojo::database::introspect::Ty { dojo::database::introspect::Ty::Struct( dojo::database::introspect::Struct { - name: 'ModelWithByteArray', + name: 'ModelWithSimpleArray', attrs: array![].span(), children: array![ dojo::database::introspect::Member { @@ -3871,7 +7634,11 @@ dojo::database::introspect::Member { dojo::database::introspect::Member { name: 'y', attrs: array![].span(), - ty: dojo::database::introspect::Ty::ByteArray + ty: dojo::database::introspect::Ty::Array( + array![ + dojo::database::introspect::Introspect::::ty() + ].span() + ) } ].span() @@ -3880,46 +7647,387 @@ dojo::database::introspect::Member { } } -impl ModelWithByteArrayModel of dojo::model::Model { - fn entity(world: dojo::world::IWorldDispatcher, keys: Span, layout: dojo::database::introspect::Layout) -> ModelWithByteArray { - let values = dojo::world::IWorldDispatcherTrait::entity( +#[derive(Drop, Serde)] +pub struct ModelWithSimpleArrayEntity { + __id: felt252, // private field + x: u16, +y: Array, + +} + +#[generate_trait] +impl ModelWithSimpleArrayEntityImpl of ModelWithSimpleArrayEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> ModelWithSimpleArrayEntity { + ModelWithSimpleArrayModelEntityImpl::get(world, entity_id) + } + + + fn get_x(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> u16 { + let values = dojo::model::ModelEntity::::get_member( world, - Self::selector(), - keys, - layout + entity_id, + 512066735765477566404754172672287371265995314501343422459174036873487219331 ); - // TODO: Generate method to deserialize from keys / values directly to avoid - // serializing to intermediate array. let mut serialized = core::array::ArrayTrait::new(); - core::array::serialize_array_helper(keys, ref serialized); core::array::serialize_array_helper(values, ref serialized); let mut serialized = core::array::ArrayTrait::span(@serialized); - let entity = core::serde::Serde::::deserialize(ref serialized); + let field_value = core::serde::Serde::::deserialize(ref serialized); - if core::option::OptionTrait::::is_none(@entity) { + if core::option::OptionTrait::::is_none(@field_value) { panic!( - "Model `ModelWithByteArray`: deserialization failed. Ensure the length of the keys tuple is matching the number of #[key] fields in the model struct." + "Field `ModelWithSimpleArray::x`: deserialization failed." ); } - core::option::OptionTrait::::unwrap(entity) - } - - #[inline(always)] - fn name() -> ByteArray { - "ModelWithByteArray" + core::option::OptionTrait::::unwrap(field_value) } - #[inline(always)] - fn namespace() -> ByteArray { - "dojo_plugin" - } + fn set_x(self: @ModelWithSimpleArrayEntity, world: dojo::world::IWorldDispatcher, value: u16) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); - #[inline(always)] - fn tag() -> ByteArray { - "dojo_plugin-ModelWithByteArray" + self.set_member( + world, + 512066735765477566404754172672287371265995314501343422459174036873487219331, + serialized.span() + ); + } + + fn get_y(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Array { + let values = dojo::model::ModelEntity::::get_member( + world, + entity_id, + 1591024729085637502504777720563487898377940395575083379770417352976841400819 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::>::deserialize(ref serialized); + + if core::option::OptionTrait::>::is_none(@field_value) { + panic!( + "Field `ModelWithSimpleArray::y`: deserialization failed." + ); + } + + core::option::OptionTrait::>::unwrap(field_value) + } + + fn set_y(self: @ModelWithSimpleArrayEntity, world: dojo::world::IWorldDispatcher, value: Array) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 1591024729085637502504777720563487898377940395575083379770417352976841400819, + serialized.span() + ); + } + +} + +#[generate_trait] +impl ModelWithSimpleArrayImpl of ModelWithSimpleArrayTrait { + fn entity_id_from_keys(player: ContractAddress) -> felt252 { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@player, ref serialized); + + core::poseidon::poseidon_hash_span(serialized.span()) + } + + fn get(world: dojo::world::IWorldDispatcher, player: ContractAddress) -> ModelWithSimpleArray { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@player, ref serialized); + + + dojo::model::Model::::get(world, serialized.span()) + } + + + fn get_x(world: dojo::world::IWorldDispatcher, player: ContractAddress) -> u16 { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@player, ref serialized); + + + let values = dojo::model::Model::::get_member( + world, + serialized.span(), + 512066735765477566404754172672287371265995314501343422459174036873487219331 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `ModelWithSimpleArray::x`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_x(self: @ModelWithSimpleArray, world: dojo::world::IWorldDispatcher, value: u16) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 512066735765477566404754172672287371265995314501343422459174036873487219331, + serialized.span() + ); + } + + fn get_y(world: dojo::world::IWorldDispatcher, player: ContractAddress) -> Array { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@player, ref serialized); + + + let values = dojo::model::Model::::get_member( + world, + serialized.span(), + 1591024729085637502504777720563487898377940395575083379770417352976841400819 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::>::deserialize(ref serialized); + + if core::option::OptionTrait::>::is_none(@field_value) { + panic!( + "Field `ModelWithSimpleArray::y`: deserialization failed." + ); + } + + core::option::OptionTrait::>::unwrap(field_value) + } + + fn set_y(self: @ModelWithSimpleArray, world: dojo::world::IWorldDispatcher, value: Array) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 1591024729085637502504777720563487898377940395575083379770417352976841400819, + serialized.span() + ); + } + +} + +impl ModelWithSimpleArrayModelEntityImpl of dojo::model::ModelEntity { + fn id(self: @ModelWithSimpleArrayEntity) -> felt252 { + *self.__id + } + + fn values(self: @ModelWithSimpleArrayEntity) -> Span { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(self.x, ref serialized); +core::serde::Serde::serialize(self.y, ref serialized); + + core::array::ArrayTrait::span(@serialized) + } + + fn from_values(entity_id: felt252, values: Span) -> ModelWithSimpleArrayEntity { + let mut serialized = array![entity_id]; + let mut i = 0; + loop { + if i >= values.len() { break; } + serialized.append(*values.at(i)); + i += 1; + }; + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let entity_values = core::serde::Serde::::deserialize(ref serialized); + if core::option::OptionTrait::::is_none(@entity_values) { + panic!( + "ModelEntity `ModelWithSimpleArrayEntity`: deserialization failed." + ); + } + core::option::OptionTrait::::unwrap(entity_values) + } + + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> ModelWithSimpleArrayEntity { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(entity_id), + dojo::model::Model::::layout() + ); + Self::from_values(entity_id, values) + } + + fn update(self: @ModelWithSimpleArrayEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + self.values(), + dojo::model::Model::::layout() + ); + } + + fn delete(self: @ModelWithSimpleArrayEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + dojo::model::Model::::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + entity_id: felt252, + member_id: felt252, + ) -> Span { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @ModelWithSimpleArrayEntity, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span, + ) { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((self.id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } +} + +impl ModelWithSimpleArrayModelImpl of dojo::model::Model { + fn get(world: dojo::world::IWorldDispatcher, keys: Span) -> ModelWithSimpleArray { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(keys), + Self::layout() + ); + + // TODO: Generate method to deserialize from keys / values directly to avoid + // serializing to intermediate array. + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(keys, ref serialized); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let entity = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@entity) { + panic!( + "Model `ModelWithSimpleArray`: deserialization failed. Ensure the length of the keys tuple is matching the number of #[key] fields in the model struct." + ); + } + + core::option::OptionTrait::::unwrap(entity) + } + + fn set( + self: @ModelWithSimpleArray, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::values(self), + Self::layout() + ); + } + + fn delete( + self: @ModelWithSimpleArray, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + keys: Span, + member_id: felt252 + ) -> Span { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + let entity_id = dojo::utils::entity_id_from_keys(keys); + dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @ModelWithSimpleArray, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span + ) { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((self.entity_id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + #[inline(always)] + fn name() -> ByteArray { + "ModelWithSimpleArray" + } + + #[inline(always)] + fn namespace() -> ByteArray { + "dojo_plugin" + } + + #[inline(always)] + fn tag() -> ByteArray { + "dojo_plugin-ModelWithSimpleArray" } #[inline(always)] @@ -3929,45 +8037,53 @@ impl ModelWithByteArrayModel of dojo::model::Model { #[inline(always)] fn selector() -> felt252 { - 1495813766814131974177657304275361143893541941399872042870855060582891570868 + 3015573168128997707047545520976347917082964620628387533056114714397499472255 } #[inline(always)] - fn instance_selector(self: @ModelWithByteArray) -> felt252 { + fn instance_selector(self: @ModelWithSimpleArray) -> felt252 { Self::selector() } #[inline(always)] fn name_hash() -> felt252 { - 2176409715042145900636260236501596599545103472111273072320531220776338338674 + 173141902001925402715103859951360389436088950156916962046507357841237663931 } #[inline(always)] fn namespace_hash() -> felt252 { 3437408695301308226171664635441698996501144546809569617702850025816833723775 } - + #[inline(always)] - fn keys(self: @ModelWithByteArray) -> Span { + fn entity_id(self: @ModelWithSimpleArray) -> felt252 { + core::poseidon::poseidon_hash_span(self.keys()) + } + + #[inline(always)] + fn keys(self: @ModelWithSimpleArray) -> Span { let mut serialized = core::array::ArrayTrait::new(); core::serde::Serde::serialize(self.player, ref serialized); + core::array::ArrayTrait::span(@serialized) } #[inline(always)] - fn values(self: @ModelWithByteArray) -> Span { + fn values(self: @ModelWithSimpleArray) -> Span { let mut serialized = core::array::ArrayTrait::new(); - core::serde::Serde::serialize(self.x, ref serialized);core::serde::Serde::serialize(self.y, ref serialized); + core::serde::Serde::serialize(self.x, ref serialized); +core::serde::Serde::serialize(self.y, ref serialized); + core::array::ArrayTrait::span(@serialized) } #[inline(always)] fn layout() -> dojo::database::introspect::Layout { - dojo::database::introspect::Introspect::::layout() + dojo::database::introspect::Introspect::::layout() } #[inline(always)] - fn instance_layout(self: @ModelWithByteArray) -> dojo::database::introspect::Layout { + fn instance_layout(self: @ModelWithSimpleArray) -> dojo::database::introspect::Layout { Self::layout() } @@ -3990,14 +8106,14 @@ impl ModelWithByteArrayModel of dojo::model::Model { } #[starknet::interface] -trait Imodel_with_byte_array { - fn ensure_abi(self: @T, model: ModelWithByteArray); +trait Imodel_with_simple_array { + fn ensure_abi(self: @T, model: ModelWithSimpleArray); } #[starknet::contract] -mod model_with_byte_array { - use super::ModelWithByteArray; - use super::Imodel_with_byte_array; +mod model_with_simple_array { + use super::ModelWithSimpleArray; + use super::Imodel_with_simple_array; #[storage] struct Storage {} @@ -4005,58 +8121,58 @@ mod model_with_byte_array { #[abi(embed_v0)] impl DojoModelImpl of dojo::model::IModel{ fn name(self: @ContractState) -> ByteArray { - dojo::model::Model::::name() + dojo::model::Model::::name() } fn namespace(self: @ContractState) -> ByteArray { - dojo::model::Model::::namespace() + dojo::model::Model::::namespace() } fn tag(self: @ContractState) -> ByteArray { - dojo::model::Model::::tag() + dojo::model::Model::::tag() } fn version(self: @ContractState) -> u8 { - dojo::model::Model::::version() + dojo::model::Model::::version() } fn selector(self: @ContractState) -> felt252 { - dojo::model::Model::::selector() + dojo::model::Model::::selector() } fn name_hash(self: @ContractState) -> felt252 { - dojo::model::Model::::name_hash() + dojo::model::Model::::name_hash() } fn namespace_hash(self: @ContractState) -> felt252 { - dojo::model::Model::::namespace_hash() + dojo::model::Model::::namespace_hash() } fn unpacked_size(self: @ContractState) -> Option { - dojo::database::introspect::Introspect::::size() + dojo::database::introspect::Introspect::::size() } fn packed_size(self: @ContractState) -> Option { - dojo::model::Model::::packed_size() + dojo::model::Model::::packed_size() } fn layout(self: @ContractState) -> dojo::database::introspect::Layout { - dojo::model::Model::::layout() + dojo::model::Model::::layout() } fn schema(self: @ContractState) -> dojo::database::introspect::Ty { - dojo::database::introspect::Introspect::::ty() + dojo::database::introspect::Introspect::::ty() } } #[abi(embed_v0)] - impl model_with_byte_arrayImpl of Imodel_with_byte_array{ - fn ensure_abi(self: @ContractState, model: ModelWithByteArray) { + impl model_with_simple_arrayImpl of Imodel_with_simple_array{ + fn ensure_abi(self: @ContractState, model: ModelWithSimpleArray) { } } } -impl ModelWithComplexArrayIntrospect<> of dojo::database::introspect::Introspect> { +impl ModelWithByteArrayIntrospect<> of dojo::database::introspect::Introspect> { #[inline(always)] fn size() -> Option { Option::None @@ -4071,7 +8187,7 @@ impl ModelWithComplexArrayIntrospect<> of dojo::database::introspect::Introspect }, dojo::database::introspect::FieldLayout { selector: 1591024729085637502504777720563487898377940395575083379770417352976841400819, - layout: dojo::database::introspect::Introspect:: + layout: dojo::database::introspect::Introspect::::layout() } ].span() @@ -4082,7 +8198,7 @@ dojo::database::introspect::FieldLayout { fn ty() -> dojo::database::introspect::Ty { dojo::database::introspect::Ty::Struct( dojo::database::introspect::Struct { - name: 'ModelWithComplexArray', + name: 'ModelWithByteArray', attrs: array![].span(), children: array![ dojo::database::introspect::Member { @@ -4098,11 +8214,7 @@ dojo::database::introspect::Member { dojo::database::introspect::Member { name: 'y', attrs: array![].span(), - ty: dojo::database::introspect::Ty::Array( - array![ - dojo::database::introspect::Introspect::::ty() - ].span() - ) + ty: dojo::database::introspect::Ty::ByteArray } ].span() @@ -4111,36 +8223,377 @@ dojo::database::introspect::Member { } } -impl ModelWithComplexArrayModel of dojo::model::Model { - fn entity(world: dojo::world::IWorldDispatcher, keys: Span, layout: dojo::database::introspect::Layout) -> ModelWithComplexArray { - let values = dojo::world::IWorldDispatcherTrait::entity( +#[derive(Drop, Serde)] +pub struct ModelWithByteArrayEntity { + __id: felt252, // private field + x: u16, +y: ByteArray, + +} + +#[generate_trait] +impl ModelWithByteArrayEntityImpl of ModelWithByteArrayEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> ModelWithByteArrayEntity { + ModelWithByteArrayModelEntityImpl::get(world, entity_id) + } + + + fn get_x(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> u16 { + let values = dojo::model::ModelEntity::::get_member( world, - Self::selector(), - keys, - layout + entity_id, + 512066735765477566404754172672287371265995314501343422459174036873487219331 ); - // TODO: Generate method to deserialize from keys / values directly to avoid - // serializing to intermediate array. let mut serialized = core::array::ArrayTrait::new(); - core::array::serialize_array_helper(keys, ref serialized); core::array::serialize_array_helper(values, ref serialized); let mut serialized = core::array::ArrayTrait::span(@serialized); - let entity = core::serde::Serde::::deserialize(ref serialized); + let field_value = core::serde::Serde::::deserialize(ref serialized); - if core::option::OptionTrait::::is_none(@entity) { + if core::option::OptionTrait::::is_none(@field_value) { panic!( - "Model `ModelWithComplexArray`: deserialization failed. Ensure the length of the keys tuple is matching the number of #[key] fields in the model struct." + "Field `ModelWithByteArray::x`: deserialization failed." ); } - core::option::OptionTrait::::unwrap(entity) + core::option::OptionTrait::::unwrap(field_value) } - #[inline(always)] - fn name() -> ByteArray { - "ModelWithComplexArray" + fn set_x(self: @ModelWithByteArrayEntity, world: dojo::world::IWorldDispatcher, value: u16) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 512066735765477566404754172672287371265995314501343422459174036873487219331, + serialized.span() + ); + } + + fn get_y(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> ByteArray { + let values = dojo::model::ModelEntity::::get_member( + world, + entity_id, + 1591024729085637502504777720563487898377940395575083379770417352976841400819 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `ModelWithByteArray::y`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_y(self: @ModelWithByteArrayEntity, world: dojo::world::IWorldDispatcher, value: ByteArray) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 1591024729085637502504777720563487898377940395575083379770417352976841400819, + serialized.span() + ); + } + +} + +#[generate_trait] +impl ModelWithByteArrayImpl of ModelWithByteArrayTrait { + fn entity_id_from_keys(player: ContractAddress) -> felt252 { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@player, ref serialized); + + core::poseidon::poseidon_hash_span(serialized.span()) + } + + fn get(world: dojo::world::IWorldDispatcher, player: ContractAddress) -> ModelWithByteArray { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@player, ref serialized); + + + dojo::model::Model::::get(world, serialized.span()) + } + + + fn get_x(world: dojo::world::IWorldDispatcher, player: ContractAddress) -> u16 { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@player, ref serialized); + + + let values = dojo::model::Model::::get_member( + world, + serialized.span(), + 512066735765477566404754172672287371265995314501343422459174036873487219331 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `ModelWithByteArray::x`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_x(self: @ModelWithByteArray, world: dojo::world::IWorldDispatcher, value: u16) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 512066735765477566404754172672287371265995314501343422459174036873487219331, + serialized.span() + ); + } + + fn get_y(world: dojo::world::IWorldDispatcher, player: ContractAddress) -> ByteArray { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@player, ref serialized); + + + let values = dojo::model::Model::::get_member( + world, + serialized.span(), + 1591024729085637502504777720563487898377940395575083379770417352976841400819 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `ModelWithByteArray::y`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_y(self: @ModelWithByteArray, world: dojo::world::IWorldDispatcher, value: ByteArray) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 1591024729085637502504777720563487898377940395575083379770417352976841400819, + serialized.span() + ); + } + +} + +impl ModelWithByteArrayModelEntityImpl of dojo::model::ModelEntity { + fn id(self: @ModelWithByteArrayEntity) -> felt252 { + *self.__id + } + + fn values(self: @ModelWithByteArrayEntity) -> Span { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(self.x, ref serialized); +core::serde::Serde::serialize(self.y, ref serialized); + + core::array::ArrayTrait::span(@serialized) + } + + fn from_values(entity_id: felt252, values: Span) -> ModelWithByteArrayEntity { + let mut serialized = array![entity_id]; + let mut i = 0; + loop { + if i >= values.len() { break; } + serialized.append(*values.at(i)); + i += 1; + }; + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let entity_values = core::serde::Serde::::deserialize(ref serialized); + if core::option::OptionTrait::::is_none(@entity_values) { + panic!( + "ModelEntity `ModelWithByteArrayEntity`: deserialization failed." + ); + } + core::option::OptionTrait::::unwrap(entity_values) + } + + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> ModelWithByteArrayEntity { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(entity_id), + dojo::model::Model::::layout() + ); + Self::from_values(entity_id, values) + } + + fn update(self: @ModelWithByteArrayEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + self.values(), + dojo::model::Model::::layout() + ); + } + + fn delete(self: @ModelWithByteArrayEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + dojo::model::Model::::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + entity_id: felt252, + member_id: felt252, + ) -> Span { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @ModelWithByteArrayEntity, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span, + ) { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((self.id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } +} + +impl ModelWithByteArrayModelImpl of dojo::model::Model { + fn get(world: dojo::world::IWorldDispatcher, keys: Span) -> ModelWithByteArray { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(keys), + Self::layout() + ); + + // TODO: Generate method to deserialize from keys / values directly to avoid + // serializing to intermediate array. + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(keys, ref serialized); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let entity = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@entity) { + panic!( + "Model `ModelWithByteArray`: deserialization failed. Ensure the length of the keys tuple is matching the number of #[key] fields in the model struct." + ); + } + + core::option::OptionTrait::::unwrap(entity) + } + + fn set( + self: @ModelWithByteArray, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::values(self), + Self::layout() + ); + } + + fn delete( + self: @ModelWithByteArray, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + keys: Span, + member_id: felt252 + ) -> Span { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + let entity_id = dojo::utils::entity_id_from_keys(keys); + dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @ModelWithByteArray, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span + ) { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((self.entity_id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + #[inline(always)] + fn name() -> ByteArray { + "ModelWithByteArray" } #[inline(always)] @@ -4150,7 +8603,7 @@ impl ModelWithComplexArrayModel of dojo::model::Model { #[inline(always)] fn tag() -> ByteArray { - "dojo_plugin-ModelWithComplexArray" + "dojo_plugin-ModelWithByteArray" } #[inline(always)] @@ -4160,45 +8613,53 @@ impl ModelWithComplexArrayModel of dojo::model::Model { #[inline(always)] fn selector() -> felt252 { - 36330270687495804813979499325154873801411429162367231362587376627277795482 + 1495813766814131974177657304275361143893541941399872042870855060582891570868 } #[inline(always)] - fn instance_selector(self: @ModelWithComplexArray) -> felt252 { + fn instance_selector(self: @ModelWithByteArray) -> felt252 { Self::selector() } #[inline(always)] fn name_hash() -> felt252 { - 2866472224509756243720005045848892642397514372569303051745174230372637769655 + 2176409715042145900636260236501596599545103472111273072320531220776338338674 } #[inline(always)] fn namespace_hash() -> felt252 { 3437408695301308226171664635441698996501144546809569617702850025816833723775 } - + #[inline(always)] - fn keys(self: @ModelWithComplexArray) -> Span { + fn entity_id(self: @ModelWithByteArray) -> felt252 { + core::poseidon::poseidon_hash_span(self.keys()) + } + + #[inline(always)] + fn keys(self: @ModelWithByteArray) -> Span { let mut serialized = core::array::ArrayTrait::new(); core::serde::Serde::serialize(self.player, ref serialized); + core::array::ArrayTrait::span(@serialized) } #[inline(always)] - fn values(self: @ModelWithComplexArray) -> Span { + fn values(self: @ModelWithByteArray) -> Span { let mut serialized = core::array::ArrayTrait::new(); - core::serde::Serde::serialize(self.x, ref serialized);core::serde::Serde::serialize(self.y, ref serialized); + core::serde::Serde::serialize(self.x, ref serialized); +core::serde::Serde::serialize(self.y, ref serialized); + core::array::ArrayTrait::span(@serialized) } #[inline(always)] fn layout() -> dojo::database::introspect::Layout { - dojo::database::introspect::Introspect::::layout() + dojo::database::introspect::Introspect::::layout() } #[inline(always)] - fn instance_layout(self: @ModelWithComplexArray) -> dojo::database::introspect::Layout { + fn instance_layout(self: @ModelWithByteArray) -> dojo::database::introspect::Layout { Self::layout() } @@ -4221,14 +8682,14 @@ impl ModelWithComplexArrayModel of dojo::model::Model { } #[starknet::interface] -trait Imodel_with_complex_array { - fn ensure_abi(self: @T, model: ModelWithComplexArray); +trait Imodel_with_byte_array { + fn ensure_abi(self: @T, model: ModelWithByteArray); } #[starknet::contract] -mod model_with_complex_array { - use super::ModelWithComplexArray; - use super::Imodel_with_complex_array; +mod model_with_byte_array { + use super::ModelWithByteArray; + use super::Imodel_with_byte_array; #[storage] struct Storage {} @@ -4236,61 +8697,61 @@ mod model_with_complex_array { #[abi(embed_v0)] impl DojoModelImpl of dojo::model::IModel{ fn name(self: @ContractState) -> ByteArray { - dojo::model::Model::::name() + dojo::model::Model::::name() } fn namespace(self: @ContractState) -> ByteArray { - dojo::model::Model::::namespace() + dojo::model::Model::::namespace() } fn tag(self: @ContractState) -> ByteArray { - dojo::model::Model::::tag() + dojo::model::Model::::tag() } fn version(self: @ContractState) -> u8 { - dojo::model::Model::::version() + dojo::model::Model::::version() } fn selector(self: @ContractState) -> felt252 { - dojo::model::Model::::selector() + dojo::model::Model::::selector() } fn name_hash(self: @ContractState) -> felt252 { - dojo::model::Model::::name_hash() + dojo::model::Model::::name_hash() } fn namespace_hash(self: @ContractState) -> felt252 { - dojo::model::Model::::namespace_hash() + dojo::model::Model::::namespace_hash() } fn unpacked_size(self: @ContractState) -> Option { - dojo::database::introspect::Introspect::::size() + dojo::database::introspect::Introspect::::size() } fn packed_size(self: @ContractState) -> Option { - dojo::model::Model::::packed_size() + dojo::model::Model::::packed_size() } fn layout(self: @ContractState) -> dojo::database::introspect::Layout { - dojo::model::Model::::layout() + dojo::model::Model::::layout() } fn schema(self: @ContractState) -> dojo::database::introspect::Ty { - dojo::database::introspect::Introspect::::ty() + dojo::database::introspect::Introspect::::ty() } } #[abi(embed_v0)] - impl model_with_complex_arrayImpl of Imodel_with_complex_array{ - fn ensure_abi(self: @ContractState, model: ModelWithComplexArray) { + impl model_with_byte_arrayImpl of Imodel_with_byte_array{ + fn ensure_abi(self: @ContractState, model: ModelWithByteArray) { } } } -impl ModelWithTupleIntrospect<> of dojo::database::introspect::Introspect> { +impl ModelWithComplexArrayIntrospect<> of dojo::database::introspect::Introspect> { #[inline(always)] fn size() -> Option { - Option::Some(4) + Option::None } fn layout() -> dojo::database::introspect::Layout { @@ -4302,13 +8763,8 @@ impl ModelWithTupleIntrospect<> of dojo::database::introspect::Introspect::layout(), -dojo::database::introspect::Introspect::::layout(), -dojo::database::introspect::Introspect::::layout() - ].span() - ) + layout: dojo::database::introspect::Introspect:: +>::layout() } ].span() ) @@ -4318,7 +8774,7 @@ dojo::database::introspect::Introspect::::layout() fn ty() -> dojo::database::introspect::Ty { dojo::database::introspect::Ty::Struct( dojo::database::introspect::Struct { - name: 'ModelWithTuple', + name: 'ModelWithComplexArray', attrs: array![].span(), children: array![ dojo::database::introspect::Member { @@ -4334,13 +8790,11 @@ dojo::database::introspect::Member { dojo::database::introspect::Member { name: 'y', attrs: array![].span(), - ty: dojo::database::introspect::Ty::Tuple( - array![ - dojo::database::introspect::Introspect::::ty(), -dojo::database::introspect::Introspect::::ty(), -dojo::database::introspect::Introspect::::ty() - ].span() - ) + ty: dojo::database::introspect::Ty::Array( + array![ + dojo::database::introspect::Introspect::::ty() + ].span() + ) } ].span() @@ -4349,36 +8803,377 @@ dojo::database::introspect::Introspect::::ty() } } -impl ModelWithTupleModel of dojo::model::Model { - fn entity(world: dojo::world::IWorldDispatcher, keys: Span, layout: dojo::database::introspect::Layout) -> ModelWithTuple { - let values = dojo::world::IWorldDispatcherTrait::entity( - world, - Self::selector(), - keys, - layout - ); +#[derive(Drop, Serde)] +pub struct ModelWithComplexArrayEntity { + __id: felt252, // private field + x: u16, +y: Array, - // TODO: Generate method to deserialize from keys / values directly to avoid +} + +#[generate_trait] +impl ModelWithComplexArrayEntityImpl of ModelWithComplexArrayEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> ModelWithComplexArrayEntity { + ModelWithComplexArrayModelEntityImpl::get(world, entity_id) + } + + + fn get_x(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> u16 { + let values = dojo::model::ModelEntity::::get_member( + world, + entity_id, + 512066735765477566404754172672287371265995314501343422459174036873487219331 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `ModelWithComplexArray::x`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_x(self: @ModelWithComplexArrayEntity, world: dojo::world::IWorldDispatcher, value: u16) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 512066735765477566404754172672287371265995314501343422459174036873487219331, + serialized.span() + ); + } + + fn get_y(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Array { + let values = dojo::model::ModelEntity::::get_member( + world, + entity_id, + 1591024729085637502504777720563487898377940395575083379770417352976841400819 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::>::deserialize(ref serialized); + + if core::option::OptionTrait::>::is_none(@field_value) { + panic!( + "Field `ModelWithComplexArray::y`: deserialization failed." + ); + } + + core::option::OptionTrait::>::unwrap(field_value) + } + + fn set_y(self: @ModelWithComplexArrayEntity, world: dojo::world::IWorldDispatcher, value: Array) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 1591024729085637502504777720563487898377940395575083379770417352976841400819, + serialized.span() + ); + } + +} + +#[generate_trait] +impl ModelWithComplexArrayImpl of ModelWithComplexArrayTrait { + fn entity_id_from_keys(player: ContractAddress) -> felt252 { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@player, ref serialized); + + core::poseidon::poseidon_hash_span(serialized.span()) + } + + fn get(world: dojo::world::IWorldDispatcher, player: ContractAddress) -> ModelWithComplexArray { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@player, ref serialized); + + + dojo::model::Model::::get(world, serialized.span()) + } + + + fn get_x(world: dojo::world::IWorldDispatcher, player: ContractAddress) -> u16 { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@player, ref serialized); + + + let values = dojo::model::Model::::get_member( + world, + serialized.span(), + 512066735765477566404754172672287371265995314501343422459174036873487219331 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `ModelWithComplexArray::x`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_x(self: @ModelWithComplexArray, world: dojo::world::IWorldDispatcher, value: u16) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 512066735765477566404754172672287371265995314501343422459174036873487219331, + serialized.span() + ); + } + + fn get_y(world: dojo::world::IWorldDispatcher, player: ContractAddress) -> Array { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@player, ref serialized); + + + let values = dojo::model::Model::::get_member( + world, + serialized.span(), + 1591024729085637502504777720563487898377940395575083379770417352976841400819 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::>::deserialize(ref serialized); + + if core::option::OptionTrait::>::is_none(@field_value) { + panic!( + "Field `ModelWithComplexArray::y`: deserialization failed." + ); + } + + core::option::OptionTrait::>::unwrap(field_value) + } + + fn set_y(self: @ModelWithComplexArray, world: dojo::world::IWorldDispatcher, value: Array) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 1591024729085637502504777720563487898377940395575083379770417352976841400819, + serialized.span() + ); + } + +} + +impl ModelWithComplexArrayModelEntityImpl of dojo::model::ModelEntity { + fn id(self: @ModelWithComplexArrayEntity) -> felt252 { + *self.__id + } + + fn values(self: @ModelWithComplexArrayEntity) -> Span { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(self.x, ref serialized); +core::serde::Serde::serialize(self.y, ref serialized); + + core::array::ArrayTrait::span(@serialized) + } + + fn from_values(entity_id: felt252, values: Span) -> ModelWithComplexArrayEntity { + let mut serialized = array![entity_id]; + let mut i = 0; + loop { + if i >= values.len() { break; } + serialized.append(*values.at(i)); + i += 1; + }; + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let entity_values = core::serde::Serde::::deserialize(ref serialized); + if core::option::OptionTrait::::is_none(@entity_values) { + panic!( + "ModelEntity `ModelWithComplexArrayEntity`: deserialization failed." + ); + } + core::option::OptionTrait::::unwrap(entity_values) + } + + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> ModelWithComplexArrayEntity { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(entity_id), + dojo::model::Model::::layout() + ); + Self::from_values(entity_id, values) + } + + fn update(self: @ModelWithComplexArrayEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + self.values(), + dojo::model::Model::::layout() + ); + } + + fn delete(self: @ModelWithComplexArrayEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + dojo::model::Model::::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + entity_id: felt252, + member_id: felt252, + ) -> Span { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @ModelWithComplexArrayEntity, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span, + ) { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((self.id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } +} + +impl ModelWithComplexArrayModelImpl of dojo::model::Model { + fn get(world: dojo::world::IWorldDispatcher, keys: Span) -> ModelWithComplexArray { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(keys), + Self::layout() + ); + + // TODO: Generate method to deserialize from keys / values directly to avoid // serializing to intermediate array. let mut serialized = core::array::ArrayTrait::new(); core::array::serialize_array_helper(keys, ref serialized); core::array::serialize_array_helper(values, ref serialized); let mut serialized = core::array::ArrayTrait::span(@serialized); - let entity = core::serde::Serde::::deserialize(ref serialized); + let entity = core::serde::Serde::::deserialize(ref serialized); - if core::option::OptionTrait::::is_none(@entity) { + if core::option::OptionTrait::::is_none(@entity) { panic!( - "Model `ModelWithTuple`: deserialization failed. Ensure the length of the keys tuple is matching the number of #[key] fields in the model struct." + "Model `ModelWithComplexArray`: deserialization failed. Ensure the length of the keys tuple is matching the number of #[key] fields in the model struct." ); } - core::option::OptionTrait::::unwrap(entity) + core::option::OptionTrait::::unwrap(entity) + } + + fn set( + self: @ModelWithComplexArray, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::values(self), + Self::layout() + ); + } + + fn delete( + self: @ModelWithComplexArray, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + keys: Span, + member_id: felt252 + ) -> Span { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + let entity_id = dojo::utils::entity_id_from_keys(keys); + dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @ModelWithComplexArray, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span + ) { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((self.entity_id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } } #[inline(always)] fn name() -> ByteArray { - "ModelWithTuple" + "ModelWithComplexArray" } #[inline(always)] @@ -4388,7 +9183,7 @@ impl ModelWithTupleModel of dojo::model::Model { #[inline(always)] fn tag() -> ByteArray { - "dojo_plugin-ModelWithTuple" + "dojo_plugin-ModelWithComplexArray" } #[inline(always)] @@ -4398,45 +9193,53 @@ impl ModelWithTupleModel of dojo::model::Model { #[inline(always)] fn selector() -> felt252 { - 2968932965114787437968555813812827702683268243780347884633996291362924490633 + 36330270687495804813979499325154873801411429162367231362587376627277795482 } #[inline(always)] - fn instance_selector(self: @ModelWithTuple) -> felt252 { + fn instance_selector(self: @ModelWithComplexArray) -> felt252 { Self::selector() } #[inline(always)] fn name_hash() -> felt252 { - 3222351670132870101782632958288197874250493316621507272653773018669253981260 + 2866472224509756243720005045848892642397514372569303051745174230372637769655 } #[inline(always)] fn namespace_hash() -> felt252 { 3437408695301308226171664635441698996501144546809569617702850025816833723775 } - + #[inline(always)] - fn keys(self: @ModelWithTuple) -> Span { + fn entity_id(self: @ModelWithComplexArray) -> felt252 { + core::poseidon::poseidon_hash_span(self.keys()) + } + + #[inline(always)] + fn keys(self: @ModelWithComplexArray) -> Span { let mut serialized = core::array::ArrayTrait::new(); core::serde::Serde::serialize(self.player, ref serialized); + core::array::ArrayTrait::span(@serialized) } #[inline(always)] - fn values(self: @ModelWithTuple) -> Span { + fn values(self: @ModelWithComplexArray) -> Span { let mut serialized = core::array::ArrayTrait::new(); - core::serde::Serde::serialize(self.x, ref serialized);core::serde::Serde::serialize(self.y, ref serialized); + core::serde::Serde::serialize(self.x, ref serialized); +core::serde::Serde::serialize(self.y, ref serialized); + core::array::ArrayTrait::span(@serialized) } #[inline(always)] fn layout() -> dojo::database::introspect::Layout { - dojo::database::introspect::Introspect::::layout() + dojo::database::introspect::Introspect::::layout() } #[inline(always)] - fn instance_layout(self: @ModelWithTuple) -> dojo::database::introspect::Layout { + fn instance_layout(self: @ModelWithComplexArray) -> dojo::database::introspect::Layout { Self::layout() } @@ -4459,14 +9262,14 @@ impl ModelWithTupleModel of dojo::model::Model { } #[starknet::interface] -trait Imodel_with_tuple { - fn ensure_abi(self: @T, model: ModelWithTuple); +trait Imodel_with_complex_array { + fn ensure_abi(self: @T, model: ModelWithComplexArray); } #[starknet::contract] -mod model_with_tuple { - use super::ModelWithTuple; - use super::Imodel_with_tuple; +mod model_with_complex_array { + use super::ModelWithComplexArray; + use super::Imodel_with_complex_array; #[storage] struct Storage {} @@ -4474,70 +9277,61 @@ mod model_with_tuple { #[abi(embed_v0)] impl DojoModelImpl of dojo::model::IModel{ fn name(self: @ContractState) -> ByteArray { - dojo::model::Model::::name() + dojo::model::Model::::name() } fn namespace(self: @ContractState) -> ByteArray { - dojo::model::Model::::namespace() + dojo::model::Model::::namespace() } fn tag(self: @ContractState) -> ByteArray { - dojo::model::Model::::tag() + dojo::model::Model::::tag() } fn version(self: @ContractState) -> u8 { - dojo::model::Model::::version() + dojo::model::Model::::version() } fn selector(self: @ContractState) -> felt252 { - dojo::model::Model::::selector() + dojo::model::Model::::selector() } fn name_hash(self: @ContractState) -> felt252 { - dojo::model::Model::::name_hash() + dojo::model::Model::::name_hash() } fn namespace_hash(self: @ContractState) -> felt252 { - dojo::model::Model::::namespace_hash() + dojo::model::Model::::namespace_hash() } fn unpacked_size(self: @ContractState) -> Option { - dojo::database::introspect::Introspect::::size() + dojo::database::introspect::Introspect::::size() } fn packed_size(self: @ContractState) -> Option { - dojo::model::Model::::packed_size() + dojo::model::Model::::packed_size() } fn layout(self: @ContractState) -> dojo::database::introspect::Layout { - dojo::model::Model::::layout() + dojo::model::Model::::layout() } fn schema(self: @ContractState) -> dojo::database::introspect::Ty { - dojo::database::introspect::Introspect::::ty() + dojo::database::introspect::Introspect::::ty() } } #[abi(embed_v0)] - impl model_with_tupleImpl of Imodel_with_tuple{ - fn ensure_abi(self: @ContractState, model: ModelWithTuple) { + impl model_with_complex_arrayImpl of Imodel_with_complex_array{ + fn ensure_abi(self: @ContractState, model: ModelWithComplexArray) { } } } -impl ModelWithTupleNoPrimitivesIntrospect<> of dojo::database::introspect::Introspect> { +impl ModelWithTupleIntrospect<> of dojo::database::introspect::Introspect> { #[inline(always)] fn size() -> Option { - let sizes : Array> = array![ - dojo::database::introspect::Introspect::::size(), -Option::Some(3) - ]; - - if dojo::database::utils::any_none(@sizes) { - return Option::None; - } - Option::Some(dojo::database::utils::sum(sizes)) - + Option::Some(4) } fn layout() -> dojo::database::introspect::Layout { @@ -4552,7 +9346,7 @@ dojo::database::introspect::FieldLayout { layout: dojo::database::introspect::Layout::Tuple( array![ dojo::database::introspect::Introspect::::layout(), -dojo::database::introspect::Introspect::::layout(), +dojo::database::introspect::Introspect::::layout(), dojo::database::introspect::Introspect::::layout() ].span() ) @@ -4565,7 +9359,7 @@ dojo::database::introspect::Introspect::::layout() fn ty() -> dojo::database::introspect::Ty { dojo::database::introspect::Ty::Struct( dojo::database::introspect::Struct { - name: 'ModelWithTupleNoPrimitives', + name: 'ModelWithTuple', attrs: array![].span(), children: array![ dojo::database::introspect::Member { @@ -4584,7 +9378,7 @@ dojo::database::introspect::Member { ty: dojo::database::introspect::Ty::Tuple( array![ dojo::database::introspect::Introspect::::ty(), -dojo::database::introspect::Introspect::::ty(), +dojo::database::introspect::Introspect::::ty(), dojo::database::introspect::Introspect::::ty() ].span() ) @@ -4596,36 +9390,377 @@ dojo::database::introspect::Introspect::::ty() } } -impl ModelWithTupleNoPrimitivesModel of dojo::model::Model { - fn entity(world: dojo::world::IWorldDispatcher, keys: Span, layout: dojo::database::introspect::Layout) -> ModelWithTupleNoPrimitives { - let values = dojo::world::IWorldDispatcherTrait::entity( - world, - Self::selector(), - keys, - layout - ); +#[derive(Drop, Serde)] +pub struct ModelWithTupleEntity { + __id: felt252, // private field + x: u16, +y: (u8, u16, u32), - // TODO: Generate method to deserialize from keys / values directly to avoid +} + +#[generate_trait] +impl ModelWithTupleEntityImpl of ModelWithTupleEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> ModelWithTupleEntity { + ModelWithTupleModelEntityImpl::get(world, entity_id) + } + + + fn get_x(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> u16 { + let values = dojo::model::ModelEntity::::get_member( + world, + entity_id, + 512066735765477566404754172672287371265995314501343422459174036873487219331 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `ModelWithTuple::x`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_x(self: @ModelWithTupleEntity, world: dojo::world::IWorldDispatcher, value: u16) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 512066735765477566404754172672287371265995314501343422459174036873487219331, + serialized.span() + ); + } + + fn get_y(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> (u8, u16, u32) { + let values = dojo::model::ModelEntity::::get_member( + world, + entity_id, + 1591024729085637502504777720563487898377940395575083379770417352976841400819 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::<(u8, u16, u32)>::deserialize(ref serialized); + + if core::option::OptionTrait::<(u8, u16, u32)>::is_none(@field_value) { + panic!( + "Field `ModelWithTuple::y`: deserialization failed." + ); + } + + core::option::OptionTrait::<(u8, u16, u32)>::unwrap(field_value) + } + + fn set_y(self: @ModelWithTupleEntity, world: dojo::world::IWorldDispatcher, value: (u8, u16, u32)) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 1591024729085637502504777720563487898377940395575083379770417352976841400819, + serialized.span() + ); + } + +} + +#[generate_trait] +impl ModelWithTupleImpl of ModelWithTupleTrait { + fn entity_id_from_keys(player: ContractAddress) -> felt252 { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@player, ref serialized); + + core::poseidon::poseidon_hash_span(serialized.span()) + } + + fn get(world: dojo::world::IWorldDispatcher, player: ContractAddress) -> ModelWithTuple { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@player, ref serialized); + + + dojo::model::Model::::get(world, serialized.span()) + } + + + fn get_x(world: dojo::world::IWorldDispatcher, player: ContractAddress) -> u16 { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@player, ref serialized); + + + let values = dojo::model::Model::::get_member( + world, + serialized.span(), + 512066735765477566404754172672287371265995314501343422459174036873487219331 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `ModelWithTuple::x`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_x(self: @ModelWithTuple, world: dojo::world::IWorldDispatcher, value: u16) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 512066735765477566404754172672287371265995314501343422459174036873487219331, + serialized.span() + ); + } + + fn get_y(world: dojo::world::IWorldDispatcher, player: ContractAddress) -> (u8, u16, u32) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@player, ref serialized); + + + let values = dojo::model::Model::::get_member( + world, + serialized.span(), + 1591024729085637502504777720563487898377940395575083379770417352976841400819 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::<(u8, u16, u32)>::deserialize(ref serialized); + + if core::option::OptionTrait::<(u8, u16, u32)>::is_none(@field_value) { + panic!( + "Field `ModelWithTuple::y`: deserialization failed." + ); + } + + core::option::OptionTrait::<(u8, u16, u32)>::unwrap(field_value) + } + + fn set_y(self: @ModelWithTuple, world: dojo::world::IWorldDispatcher, value: (u8, u16, u32)) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 1591024729085637502504777720563487898377940395575083379770417352976841400819, + serialized.span() + ); + } + +} + +impl ModelWithTupleModelEntityImpl of dojo::model::ModelEntity { + fn id(self: @ModelWithTupleEntity) -> felt252 { + *self.__id + } + + fn values(self: @ModelWithTupleEntity) -> Span { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(self.x, ref serialized); +core::serde::Serde::serialize(self.y, ref serialized); + + core::array::ArrayTrait::span(@serialized) + } + + fn from_values(entity_id: felt252, values: Span) -> ModelWithTupleEntity { + let mut serialized = array![entity_id]; + let mut i = 0; + loop { + if i >= values.len() { break; } + serialized.append(*values.at(i)); + i += 1; + }; + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let entity_values = core::serde::Serde::::deserialize(ref serialized); + if core::option::OptionTrait::::is_none(@entity_values) { + panic!( + "ModelEntity `ModelWithTupleEntity`: deserialization failed." + ); + } + core::option::OptionTrait::::unwrap(entity_values) + } + + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> ModelWithTupleEntity { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(entity_id), + dojo::model::Model::::layout() + ); + Self::from_values(entity_id, values) + } + + fn update(self: @ModelWithTupleEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + self.values(), + dojo::model::Model::::layout() + ); + } + + fn delete(self: @ModelWithTupleEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + dojo::model::Model::::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + entity_id: felt252, + member_id: felt252, + ) -> Span { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @ModelWithTupleEntity, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span, + ) { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((self.id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } +} + +impl ModelWithTupleModelImpl of dojo::model::Model { + fn get(world: dojo::world::IWorldDispatcher, keys: Span) -> ModelWithTuple { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(keys), + Self::layout() + ); + + // TODO: Generate method to deserialize from keys / values directly to avoid // serializing to intermediate array. let mut serialized = core::array::ArrayTrait::new(); core::array::serialize_array_helper(keys, ref serialized); core::array::serialize_array_helper(values, ref serialized); let mut serialized = core::array::ArrayTrait::span(@serialized); - let entity = core::serde::Serde::::deserialize(ref serialized); + let entity = core::serde::Serde::::deserialize(ref serialized); - if core::option::OptionTrait::::is_none(@entity) { + if core::option::OptionTrait::::is_none(@entity) { panic!( - "Model `ModelWithTupleNoPrimitives`: deserialization failed. Ensure the length of the keys tuple is matching the number of #[key] fields in the model struct." + "Model `ModelWithTuple`: deserialization failed. Ensure the length of the keys tuple is matching the number of #[key] fields in the model struct." ); } - core::option::OptionTrait::::unwrap(entity) + core::option::OptionTrait::::unwrap(entity) + } + + fn set( + self: @ModelWithTuple, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::values(self), + Self::layout() + ); + } + + fn delete( + self: @ModelWithTuple, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + keys: Span, + member_id: felt252 + ) -> Span { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + let entity_id = dojo::utils::entity_id_from_keys(keys); + dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @ModelWithTuple, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span + ) { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((self.entity_id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } } #[inline(always)] fn name() -> ByteArray { - "ModelWithTupleNoPrimitives" + "ModelWithTuple" } #[inline(always)] @@ -4635,7 +9770,7 @@ impl ModelWithTupleNoPrimitivesModel of dojo::model::Model ByteArray { - "dojo_plugin-ModelWithTupleNoPrimitives" + "dojo_plugin-ModelWithTuple" } #[inline(always)] @@ -4645,45 +9780,53 @@ impl ModelWithTupleNoPrimitivesModel of dojo::model::Model felt252 { - 1303002480984182254910512996281734914702552284127358821084351389028444664680 + 2968932965114787437968555813812827702683268243780347884633996291362924490633 } #[inline(always)] - fn instance_selector(self: @ModelWithTupleNoPrimitives) -> felt252 { + fn instance_selector(self: @ModelWithTuple) -> felt252 { Self::selector() } #[inline(always)] fn name_hash() -> felt252 { - 157059227407493660591195028728750607977045261142495925435047270200565107096 + 3222351670132870101782632958288197874250493316621507272653773018669253981260 } #[inline(always)] fn namespace_hash() -> felt252 { 3437408695301308226171664635441698996501144546809569617702850025816833723775 } - + #[inline(always)] - fn keys(self: @ModelWithTupleNoPrimitives) -> Span { + fn entity_id(self: @ModelWithTuple) -> felt252 { + core::poseidon::poseidon_hash_span(self.keys()) + } + + #[inline(always)] + fn keys(self: @ModelWithTuple) -> Span { let mut serialized = core::array::ArrayTrait::new(); core::serde::Serde::serialize(self.player, ref serialized); + core::array::ArrayTrait::span(@serialized) } #[inline(always)] - fn values(self: @ModelWithTupleNoPrimitives) -> Span { + fn values(self: @ModelWithTuple) -> Span { let mut serialized = core::array::ArrayTrait::new(); - core::serde::Serde::serialize(self.x, ref serialized);core::serde::Serde::serialize(self.y, ref serialized); + core::serde::Serde::serialize(self.x, ref serialized); +core::serde::Serde::serialize(self.y, ref serialized); + core::array::ArrayTrait::span(@serialized) } #[inline(always)] fn layout() -> dojo::database::introspect::Layout { - dojo::database::introspect::Introspect::::layout() + dojo::database::introspect::Introspect::::layout() } #[inline(always)] - fn instance_layout(self: @ModelWithTupleNoPrimitives) -> dojo::database::introspect::Layout { + fn instance_layout(self: @ModelWithTuple) -> dojo::database::introspect::Layout { Self::layout() } @@ -4706,14 +9849,14 @@ impl ModelWithTupleNoPrimitivesModel of dojo::model::Model { - fn ensure_abi(self: @T, model: ModelWithTupleNoPrimitives); +trait Imodel_with_tuple { + fn ensure_abi(self: @T, model: ModelWithTuple); } #[starknet::contract] -mod model_with_tuple_no_primitives { - use super::ModelWithTupleNoPrimitives; - use super::Imodel_with_tuple_no_primitives; +mod model_with_tuple { + use super::ModelWithTuple; + use super::Imodel_with_tuple; #[storage] struct Storage {} @@ -4721,71 +9864,1357 @@ mod model_with_tuple_no_primitives { #[abi(embed_v0)] impl DojoModelImpl of dojo::model::IModel{ fn name(self: @ContractState) -> ByteArray { - dojo::model::Model::::name() + dojo::model::Model::::name() } fn namespace(self: @ContractState) -> ByteArray { - dojo::model::Model::::namespace() + dojo::model::Model::::namespace() } fn tag(self: @ContractState) -> ByteArray { - dojo::model::Model::::tag() + dojo::model::Model::::tag() } fn version(self: @ContractState) -> u8 { - dojo::model::Model::::version() + dojo::model::Model::::version() } fn selector(self: @ContractState) -> felt252 { - dojo::model::Model::::selector() + dojo::model::Model::::selector() } fn name_hash(self: @ContractState) -> felt252 { - dojo::model::Model::::name_hash() + dojo::model::Model::::name_hash() } fn namespace_hash(self: @ContractState) -> felt252 { - dojo::model::Model::::namespace_hash() + dojo::model::Model::::namespace_hash() } fn unpacked_size(self: @ContractState) -> Option { - dojo::database::introspect::Introspect::::size() + dojo::database::introspect::Introspect::::size() } fn packed_size(self: @ContractState) -> Option { - dojo::model::Model::::packed_size() + dojo::model::Model::::packed_size() } fn layout(self: @ContractState) -> dojo::database::introspect::Layout { - dojo::model::Model::::layout() + dojo::model::Model::::layout() } fn schema(self: @ContractState) -> dojo::database::introspect::Ty { - dojo::database::introspect::Introspect::::ty() + dojo::database::introspect::Introspect::::ty() } } #[abi(embed_v0)] - impl model_with_tuple_no_primitivesImpl of Imodel_with_tuple_no_primitives{ - fn ensure_abi(self: @ContractState, model: ModelWithTupleNoPrimitives) { + impl model_with_tupleImpl of Imodel_with_tuple{ + fn ensure_abi(self: @ContractState, model: ModelWithTuple) { } } } -//! > expected_diagnostics -error: A Dojo model must have zero or one dojo::model attribute. - --> test_src/lib.cairo:1:1 -#[dojo::model(version: 0)] -^************************^ +impl ModelWithTupleNoPrimitivesIntrospect<> of dojo::database::introspect::Introspect> { + #[inline(always)] + fn size() -> Option { + let sizes : Array> = array![ + dojo::database::introspect::Introspect::::size(), +Option::Some(3) + ]; -error: Too many 'version' attributes for dojo::model - --> test_src/lib.cairo:9:1 -#[dojo::model(version: 0, version: 0)] -^************************************^ + if dojo::database::utils::any_none(@sizes) { + return Option::None; + } + Option::Some(dojo::database::utils::sum(sizes)) + + } -error: The argument 'version' of dojo::model must be an integer - --> test_src/lib.cairo:16:24 -#[dojo::model(version: hello)] + fn layout() -> dojo::database::introspect::Layout { + dojo::database::introspect::Layout::Struct( + array![ + dojo::database::introspect::FieldLayout { + selector: 512066735765477566404754172672287371265995314501343422459174036873487219331, + layout: dojo::database::introspect::Introspect::::layout() + }, +dojo::database::introspect::FieldLayout { + selector: 1591024729085637502504777720563487898377940395575083379770417352976841400819, + layout: dojo::database::introspect::Layout::Tuple( + array![ + dojo::database::introspect::Introspect::::layout(), +dojo::database::introspect::Introspect::::layout(), +dojo::database::introspect::Introspect::::layout() + ].span() + ) + } + ].span() + ) + } + + #[inline(always)] + fn ty() -> dojo::database::introspect::Ty { + dojo::database::introspect::Ty::Struct( + dojo::database::introspect::Struct { + name: 'ModelWithTupleNoPrimitives', + attrs: array![].span(), + children: array![ + dojo::database::introspect::Member { + name: 'player', + attrs: array!['key'].span(), + ty: dojo::database::introspect::Introspect::::ty() + }, +dojo::database::introspect::Member { + name: 'x', + attrs: array![].span(), + ty: dojo::database::introspect::Introspect::::ty() + }, +dojo::database::introspect::Member { + name: 'y', + attrs: array![].span(), + ty: dojo::database::introspect::Ty::Tuple( + array![ + dojo::database::introspect::Introspect::::ty(), +dojo::database::introspect::Introspect::::ty(), +dojo::database::introspect::Introspect::::ty() + ].span() + ) + } + + ].span() + } + ) + } +} + +#[derive(Drop, Serde)] +pub struct ModelWithTupleNoPrimitivesEntity { + __id: felt252, // private field + x: u16, +y: (u8, Vec3, u32), + +} + +#[generate_trait] +impl ModelWithTupleNoPrimitivesEntityImpl of ModelWithTupleNoPrimitivesEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> ModelWithTupleNoPrimitivesEntity { + ModelWithTupleNoPrimitivesModelEntityImpl::get(world, entity_id) + } + + + fn get_x(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> u16 { + let values = dojo::model::ModelEntity::::get_member( + world, + entity_id, + 512066735765477566404754172672287371265995314501343422459174036873487219331 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `ModelWithTupleNoPrimitives::x`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_x(self: @ModelWithTupleNoPrimitivesEntity, world: dojo::world::IWorldDispatcher, value: u16) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 512066735765477566404754172672287371265995314501343422459174036873487219331, + serialized.span() + ); + } + + fn get_y(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> (u8, Vec3, u32) { + let values = dojo::model::ModelEntity::::get_member( + world, + entity_id, + 1591024729085637502504777720563487898377940395575083379770417352976841400819 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::<(u8, Vec3, u32)>::deserialize(ref serialized); + + if core::option::OptionTrait::<(u8, Vec3, u32)>::is_none(@field_value) { + panic!( + "Field `ModelWithTupleNoPrimitives::y`: deserialization failed." + ); + } + + core::option::OptionTrait::<(u8, Vec3, u32)>::unwrap(field_value) + } + + fn set_y(self: @ModelWithTupleNoPrimitivesEntity, world: dojo::world::IWorldDispatcher, value: (u8, Vec3, u32)) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 1591024729085637502504777720563487898377940395575083379770417352976841400819, + serialized.span() + ); + } + +} + +#[generate_trait] +impl ModelWithTupleNoPrimitivesImpl of ModelWithTupleNoPrimitivesTrait { + fn entity_id_from_keys(player: ContractAddress) -> felt252 { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@player, ref serialized); + + core::poseidon::poseidon_hash_span(serialized.span()) + } + + fn get(world: dojo::world::IWorldDispatcher, player: ContractAddress) -> ModelWithTupleNoPrimitives { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@player, ref serialized); + + + dojo::model::Model::::get(world, serialized.span()) + } + + + fn get_x(world: dojo::world::IWorldDispatcher, player: ContractAddress) -> u16 { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@player, ref serialized); + + + let values = dojo::model::Model::::get_member( + world, + serialized.span(), + 512066735765477566404754172672287371265995314501343422459174036873487219331 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@field_value) { + panic!( + "Field `ModelWithTupleNoPrimitives::x`: deserialization failed." + ); + } + + core::option::OptionTrait::::unwrap(field_value) + } + + fn set_x(self: @ModelWithTupleNoPrimitives, world: dojo::world::IWorldDispatcher, value: u16) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 512066735765477566404754172672287371265995314501343422459174036873487219331, + serialized.span() + ); + } + + fn get_y(world: dojo::world::IWorldDispatcher, player: ContractAddress) -> (u8, Vec3, u32) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@player, ref serialized); + + + let values = dojo::model::Model::::get_member( + world, + serialized.span(), + 1591024729085637502504777720563487898377940395575083379770417352976841400819 + ); + + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let field_value = core::serde::Serde::<(u8, Vec3, u32)>::deserialize(ref serialized); + + if core::option::OptionTrait::<(u8, Vec3, u32)>::is_none(@field_value) { + panic!( + "Field `ModelWithTupleNoPrimitives::y`: deserialization failed." + ); + } + + core::option::OptionTrait::<(u8, Vec3, u32)>::unwrap(field_value) + } + + fn set_y(self: @ModelWithTupleNoPrimitives, world: dojo::world::IWorldDispatcher, value: (u8, Vec3, u32)) { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(@value, ref serialized); + + self.set_member( + world, + 1591024729085637502504777720563487898377940395575083379770417352976841400819, + serialized.span() + ); + } + +} + +impl ModelWithTupleNoPrimitivesModelEntityImpl of dojo::model::ModelEntity { + fn id(self: @ModelWithTupleNoPrimitivesEntity) -> felt252 { + *self.__id + } + + fn values(self: @ModelWithTupleNoPrimitivesEntity) -> Span { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(self.x, ref serialized); +core::serde::Serde::serialize(self.y, ref serialized); + + core::array::ArrayTrait::span(@serialized) + } + + fn from_values(entity_id: felt252, values: Span) -> ModelWithTupleNoPrimitivesEntity { + let mut serialized = array![entity_id]; + let mut i = 0; + loop { + if i >= values.len() { break; } + serialized.append(*values.at(i)); + i += 1; + }; + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let entity_values = core::serde::Serde::::deserialize(ref serialized); + if core::option::OptionTrait::::is_none(@entity_values) { + panic!( + "ModelEntity `ModelWithTupleNoPrimitivesEntity`: deserialization failed." + ); + } + core::option::OptionTrait::::unwrap(entity_values) + } + + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> ModelWithTupleNoPrimitivesEntity { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(entity_id), + dojo::model::Model::::layout() + ); + Self::from_values(entity_id, values) + } + + fn update(self: @ModelWithTupleNoPrimitivesEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + self.values(), + dojo::model::Model::::layout() + ); + } + + fn delete(self: @ModelWithTupleNoPrimitivesEntity, world: dojo::world::IWorldDispatcher) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::Id(self.id()), + dojo::model::Model::::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + entity_id: felt252, + member_id: felt252, + ) -> Span { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @ModelWithTupleNoPrimitivesEntity, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span, + ) { + match dojo::utils::find_model_field_layout(dojo::model::Model::::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + dojo::model::Model::::selector(), + dojo::world::ModelIndex::MemberId((self.id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } +} + +impl ModelWithTupleNoPrimitivesModelImpl of dojo::model::Model { + fn get(world: dojo::world::IWorldDispatcher, keys: Span) -> ModelWithTupleNoPrimitives { + let values = dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(keys), + Self::layout() + ); + + // TODO: Generate method to deserialize from keys / values directly to avoid + // serializing to intermediate array. + let mut serialized = core::array::ArrayTrait::new(); + core::array::serialize_array_helper(keys, ref serialized); + core::array::serialize_array_helper(values, ref serialized); + let mut serialized = core::array::ArrayTrait::span(@serialized); + + let entity = core::serde::Serde::::deserialize(ref serialized); + + if core::option::OptionTrait::::is_none(@entity) { + panic!( + "Model `ModelWithTupleNoPrimitives`: deserialization failed. Ensure the length of the keys tuple is matching the number of #[key] fields in the model struct." + ); + } + + core::option::OptionTrait::::unwrap(entity) + } + + fn set( + self: @ModelWithTupleNoPrimitives, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::values(self), + Self::layout() + ); + } + + fn delete( + self: @ModelWithTupleNoPrimitives, + world: dojo::world::IWorldDispatcher + ) { + dojo::world::IWorldDispatcherTrait::delete_entity( + world, + Self::selector(), + dojo::world::ModelIndex::Keys(Self::keys(self)), + Self::layout() + ); + } + + fn get_member( + world: dojo::world::IWorldDispatcher, + keys: Span, + member_id: felt252 + ) -> Span { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + let entity_id = dojo::utils::entity_id_from_keys(keys); + dojo::world::IWorldDispatcherTrait::entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((entity_id, member_id)), + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + fn set_member( + self: @ModelWithTupleNoPrimitives, + world: dojo::world::IWorldDispatcher, + member_id: felt252, + values: Span + ) { + match dojo::utils::find_model_field_layout(Self::layout(), member_id) { + Option::Some(field_layout) => { + dojo::world::IWorldDispatcherTrait::set_entity( + world, + Self::selector(), + dojo::world::ModelIndex::MemberId((self.entity_id(), member_id)), + values, + field_layout + ) + }, + Option::None => core::panic_with_felt252('bad member id') + } + } + + #[inline(always)] + fn name() -> ByteArray { + "ModelWithTupleNoPrimitives" + } + + #[inline(always)] + fn namespace() -> ByteArray { + "dojo_plugin" + } + + #[inline(always)] + fn tag() -> ByteArray { + "dojo_plugin-ModelWithTupleNoPrimitives" + } + + #[inline(always)] + fn version() -> u8 { + 1 + } + + #[inline(always)] + fn selector() -> felt252 { + 1303002480984182254910512996281734914702552284127358821084351389028444664680 + } + + #[inline(always)] + fn instance_selector(self: @ModelWithTupleNoPrimitives) -> felt252 { + Self::selector() + } + + #[inline(always)] + fn name_hash() -> felt252 { + 157059227407493660591195028728750607977045261142495925435047270200565107096 + } + + #[inline(always)] + fn namespace_hash() -> felt252 { + 3437408695301308226171664635441698996501144546809569617702850025816833723775 + } + + #[inline(always)] + fn entity_id(self: @ModelWithTupleNoPrimitives) -> felt252 { + core::poseidon::poseidon_hash_span(self.keys()) + } + + #[inline(always)] + fn keys(self: @ModelWithTupleNoPrimitives) -> Span { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(self.player, ref serialized); + + core::array::ArrayTrait::span(@serialized) + } + + #[inline(always)] + fn values(self: @ModelWithTupleNoPrimitives) -> Span { + let mut serialized = core::array::ArrayTrait::new(); + core::serde::Serde::serialize(self.x, ref serialized); +core::serde::Serde::serialize(self.y, ref serialized); + + core::array::ArrayTrait::span(@serialized) + } + + #[inline(always)] + fn layout() -> dojo::database::introspect::Layout { + dojo::database::introspect::Introspect::::layout() + } + + #[inline(always)] + fn instance_layout(self: @ModelWithTupleNoPrimitives) -> dojo::database::introspect::Layout { + Self::layout() + } + + #[inline(always)] + fn packed_size() -> Option { + let layout = Self::layout(); + + match layout { + dojo::database::introspect::Layout::Fixed(layout) => { + let mut span_layout = layout; + Option::Some(dojo::packing::calculate_packed_size(ref span_layout)) + }, + dojo::database::introspect::Layout::Struct(_) => Option::None, + dojo::database::introspect::Layout::Array(_) => Option::None, + dojo::database::introspect::Layout::Tuple(_) => Option::None, + dojo::database::introspect::Layout::Enum(_) => Option::None, + dojo::database::introspect::Layout::ByteArray => Option::None, + } + } +} + +#[starknet::interface] +trait Imodel_with_tuple_no_primitives { + fn ensure_abi(self: @T, model: ModelWithTupleNoPrimitives); +} + +#[starknet::contract] +mod model_with_tuple_no_primitives { + use super::ModelWithTupleNoPrimitives; + use super::Imodel_with_tuple_no_primitives; + + #[storage] + struct Storage {} + + #[abi(embed_v0)] + impl DojoModelImpl of dojo::model::IModel{ + fn name(self: @ContractState) -> ByteArray { + dojo::model::Model::::name() + } + + fn namespace(self: @ContractState) -> ByteArray { + dojo::model::Model::::namespace() + } + + fn tag(self: @ContractState) -> ByteArray { + dojo::model::Model::::tag() + } + + fn version(self: @ContractState) -> u8 { + dojo::model::Model::::version() + } + + fn selector(self: @ContractState) -> felt252 { + dojo::model::Model::::selector() + } + + fn name_hash(self: @ContractState) -> felt252 { + dojo::model::Model::::name_hash() + } + + fn namespace_hash(self: @ContractState) -> felt252 { + dojo::model::Model::::namespace_hash() + } + + fn unpacked_size(self: @ContractState) -> Option { + dojo::database::introspect::Introspect::::size() + } + + fn packed_size(self: @ContractState) -> Option { + dojo::model::Model::::packed_size() + } + + fn layout(self: @ContractState) -> dojo::database::introspect::Layout { + dojo::model::Model::::layout() + } + + fn schema(self: @ContractState) -> dojo::database::introspect::Ty { + dojo::database::introspect::Introspect::::ty() + } + } + + #[abi(embed_v0)] + impl model_with_tuple_no_primitivesImpl of Imodel_with_tuple_no_primitives{ + fn ensure_abi(self: @ContractState, model: ModelWithTupleNoPrimitives) { + } + } +} +impl BadModelMultipleVersionsEntityDrop of core::traits::Drop::; +impl BadModelMultipleVersionsEntitySerde of core::serde::Serde:: { + fn serialize(self: @BadModelMultipleVersionsEntity, ref output: core::array::Array) { + core::serde::Serde::serialize(self.__id, ref output); + core::serde::Serde::serialize(self.v, ref output) + } + fn deserialize(ref serialized: core::array::Span) -> core::option::Option { + core::option::Option::Some(BadModelMultipleVersionsEntity { + __id: core::serde::Serde::deserialize(ref serialized)?, + v: core::serde::Serde::deserialize(ref serialized)?, + }) + } +} +trait BadModelMultipleVersionsEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> BadModelMultipleVersionsEntity; + + + fn get_v(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Vec3; + + fn set_v(self: @BadModelMultipleVersionsEntity, world: dojo::world::IWorldDispatcher, value: Vec3); + +} +trait BadModelMultipleVersionsTrait { + fn entity_id_from_keys(id: felt252) -> felt252; + + fn get(world: dojo::world::IWorldDispatcher, id: felt252) -> BadModelMultipleVersions; + + + fn get_v(world: dojo::world::IWorldDispatcher, id: felt252) -> Vec3; + + fn set_v(self: @BadModelMultipleVersions, world: dojo::world::IWorldDispatcher, value: Vec3); + +} +impl BadModelBadVersionTypeEntityDrop of core::traits::Drop::; +impl BadModelBadVersionTypeEntitySerde of core::serde::Serde:: { + fn serialize(self: @BadModelBadVersionTypeEntity, ref output: core::array::Array) { + core::serde::Serde::serialize(self.__id, ref output); + core::serde::Serde::serialize(self.v, ref output) + } + fn deserialize(ref serialized: core::array::Span) -> core::option::Option { + core::option::Option::Some(BadModelBadVersionTypeEntity { + __id: core::serde::Serde::deserialize(ref serialized)?, + v: core::serde::Serde::deserialize(ref serialized)?, + }) + } +} +trait BadModelBadVersionTypeEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> BadModelBadVersionTypeEntity; + + + fn get_v(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Vec3; + + fn set_v(self: @BadModelBadVersionTypeEntity, world: dojo::world::IWorldDispatcher, value: Vec3); + +} +trait BadModelBadVersionTypeTrait { + fn entity_id_from_keys(id: felt252) -> felt252; + + fn get(world: dojo::world::IWorldDispatcher, id: felt252) -> BadModelBadVersionType; + + + fn get_v(world: dojo::world::IWorldDispatcher, id: felt252) -> Vec3; + + fn set_v(self: @BadModelBadVersionType, world: dojo::world::IWorldDispatcher, value: Vec3); + +} +impl BadModelNoVersionValueEntityDrop of core::traits::Drop::; +impl BadModelNoVersionValueEntitySerde of core::serde::Serde:: { + fn serialize(self: @BadModelNoVersionValueEntity, ref output: core::array::Array) { + core::serde::Serde::serialize(self.__id, ref output); + core::serde::Serde::serialize(self.v, ref output) + } + fn deserialize(ref serialized: core::array::Span) -> core::option::Option { + core::option::Option::Some(BadModelNoVersionValueEntity { + __id: core::serde::Serde::deserialize(ref serialized)?, + v: core::serde::Serde::deserialize(ref serialized)?, + }) + } +} +trait BadModelNoVersionValueEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> BadModelNoVersionValueEntity; + + + fn get_v(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Vec3; + + fn set_v(self: @BadModelNoVersionValueEntity, world: dojo::world::IWorldDispatcher, value: Vec3); + +} +trait BadModelNoVersionValueTrait { + fn entity_id_from_keys(id: felt252) -> felt252; + + fn get(world: dojo::world::IWorldDispatcher, id: felt252) -> BadModelNoVersionValue; + + + fn get_v(world: dojo::world::IWorldDispatcher, id: felt252) -> Vec3; + + fn set_v(self: @BadModelNoVersionValue, world: dojo::world::IWorldDispatcher, value: Vec3); + +} +impl BadModelUnexpectedArgWithValueEntityDrop of core::traits::Drop::; +impl BadModelUnexpectedArgWithValueEntitySerde of core::serde::Serde:: { + fn serialize(self: @BadModelUnexpectedArgWithValueEntity, ref output: core::array::Array) { + core::serde::Serde::serialize(self.__id, ref output); + core::serde::Serde::serialize(self.v, ref output) + } + fn deserialize(ref serialized: core::array::Span) -> core::option::Option { + core::option::Option::Some(BadModelUnexpectedArgWithValueEntity { + __id: core::serde::Serde::deserialize(ref serialized)?, + v: core::serde::Serde::deserialize(ref serialized)?, + }) + } +} +trait BadModelUnexpectedArgWithValueEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> BadModelUnexpectedArgWithValueEntity; + + + fn get_v(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Vec3; + + fn set_v(self: @BadModelUnexpectedArgWithValueEntity, world: dojo::world::IWorldDispatcher, value: Vec3); + +} +trait BadModelUnexpectedArgWithValueTrait { + fn entity_id_from_keys(id: felt252) -> felt252; + + fn get(world: dojo::world::IWorldDispatcher, id: felt252) -> BadModelUnexpectedArgWithValue; + + + fn get_v(world: dojo::world::IWorldDispatcher, id: felt252) -> Vec3; + + fn set_v(self: @BadModelUnexpectedArgWithValue, world: dojo::world::IWorldDispatcher, value: Vec3); + +} +impl BadModelUnexpectedArgEntityDrop of core::traits::Drop::; +impl BadModelUnexpectedArgEntitySerde of core::serde::Serde:: { + fn serialize(self: @BadModelUnexpectedArgEntity, ref output: core::array::Array) { + core::serde::Serde::serialize(self.__id, ref output); + core::serde::Serde::serialize(self.v, ref output) + } + fn deserialize(ref serialized: core::array::Span) -> core::option::Option { + core::option::Option::Some(BadModelUnexpectedArgEntity { + __id: core::serde::Serde::deserialize(ref serialized)?, + v: core::serde::Serde::deserialize(ref serialized)?, + }) + } +} +trait BadModelUnexpectedArgEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> BadModelUnexpectedArgEntity; + + + fn get_v(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Vec3; + + fn set_v(self: @BadModelUnexpectedArgEntity, world: dojo::world::IWorldDispatcher, value: Vec3); + +} +trait BadModelUnexpectedArgTrait { + fn entity_id_from_keys(id: felt252) -> felt252; + + fn get(world: dojo::world::IWorldDispatcher, id: felt252) -> BadModelUnexpectedArg; + + + fn get_v(world: dojo::world::IWorldDispatcher, id: felt252) -> Vec3; + + fn set_v(self: @BadModelUnexpectedArg, world: dojo::world::IWorldDispatcher, value: Vec3); + +} +impl BadModelNotSupportedVersionEntityDrop of core::traits::Drop::; +impl BadModelNotSupportedVersionEntitySerde of core::serde::Serde:: { + fn serialize(self: @BadModelNotSupportedVersionEntity, ref output: core::array::Array) { + core::serde::Serde::serialize(self.__id, ref output); + core::serde::Serde::serialize(self.v, ref output) + } + fn deserialize(ref serialized: core::array::Span) -> core::option::Option { + core::option::Option::Some(BadModelNotSupportedVersionEntity { + __id: core::serde::Serde::deserialize(ref serialized)?, + v: core::serde::Serde::deserialize(ref serialized)?, + }) + } +} +trait BadModelNotSupportedVersionEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> BadModelNotSupportedVersionEntity; + + + fn get_v(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Vec3; + + fn set_v(self: @BadModelNotSupportedVersionEntity, world: dojo::world::IWorldDispatcher, value: Vec3); + +} +trait BadModelNotSupportedVersionTrait { + fn entity_id_from_keys(id: felt252) -> felt252; + + fn get(world: dojo::world::IWorldDispatcher, id: felt252) -> BadModelNotSupportedVersion; + + + fn get_v(world: dojo::world::IWorldDispatcher, id: felt252) -> Vec3; + + fn set_v(self: @BadModelNotSupportedVersion, world: dojo::world::IWorldDispatcher, value: Vec3); + +} +impl Modelv0EntityDrop of core::traits::Drop::; +impl Modelv0EntitySerde of core::serde::Serde:: { + fn serialize(self: @Modelv0Entity, ref output: core::array::Array) { + core::serde::Serde::serialize(self.__id, ref output); + core::serde::Serde::serialize(self.v, ref output) + } + fn deserialize(ref serialized: core::array::Span) -> core::option::Option { + core::option::Option::Some(Modelv0Entity { + __id: core::serde::Serde::deserialize(ref serialized)?, + v: core::serde::Serde::deserialize(ref serialized)?, + }) + } +} +trait Modelv0EntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Modelv0Entity; + + + fn get_v(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Vec3; + + fn set_v(self: @Modelv0Entity, world: dojo::world::IWorldDispatcher, value: Vec3); + +} +trait Modelv0Trait { + fn entity_id_from_keys(id: felt252) -> felt252; + + fn get(world: dojo::world::IWorldDispatcher, id: felt252) -> Modelv0; + + + fn get_v(world: dojo::world::IWorldDispatcher, id: felt252) -> Vec3; + + fn set_v(self: @Modelv0, world: dojo::world::IWorldDispatcher, value: Vec3); + +} +impl ModelWithBadNamespaceFormatEntityDrop of core::traits::Drop::; +impl ModelWithBadNamespaceFormatEntitySerde of core::serde::Serde:: { + fn serialize(self: @ModelWithBadNamespaceFormatEntity, ref output: core::array::Array) { + core::serde::Serde::serialize(self.__id, ref output); + core::serde::Serde::serialize(self.v, ref output) + } + fn deserialize(ref serialized: core::array::Span) -> core::option::Option { + core::option::Option::Some(ModelWithBadNamespaceFormatEntity { + __id: core::serde::Serde::deserialize(ref serialized)?, + v: core::serde::Serde::deserialize(ref serialized)?, + }) + } +} +trait ModelWithBadNamespaceFormatEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> ModelWithBadNamespaceFormatEntity; + + + fn get_v(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Vec3; + + fn set_v(self: @ModelWithBadNamespaceFormatEntity, world: dojo::world::IWorldDispatcher, value: Vec3); + +} +trait ModelWithBadNamespaceFormatTrait { + fn entity_id_from_keys(id: felt252) -> felt252; + + fn get(world: dojo::world::IWorldDispatcher, id: felt252) -> ModelWithBadNamespaceFormat; + + + fn get_v(world: dojo::world::IWorldDispatcher, id: felt252) -> Vec3; + + fn set_v(self: @ModelWithBadNamespaceFormat, world: dojo::world::IWorldDispatcher, value: Vec3); + +} +impl ModelWithShortStringNamespaceEntityDrop of core::traits::Drop::; +impl ModelWithShortStringNamespaceEntitySerde of core::serde::Serde:: { + fn serialize(self: @ModelWithShortStringNamespaceEntity, ref output: core::array::Array) { + core::serde::Serde::serialize(self.__id, ref output); + core::serde::Serde::serialize(self.v, ref output) + } + fn deserialize(ref serialized: core::array::Span) -> core::option::Option { + core::option::Option::Some(ModelWithShortStringNamespaceEntity { + __id: core::serde::Serde::deserialize(ref serialized)?, + v: core::serde::Serde::deserialize(ref serialized)?, + }) + } +} +trait ModelWithShortStringNamespaceEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> ModelWithShortStringNamespaceEntity; + + + fn get_v(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Vec3; + + fn set_v(self: @ModelWithShortStringNamespaceEntity, world: dojo::world::IWorldDispatcher, value: Vec3); + +} +trait ModelWithShortStringNamespaceTrait { + fn entity_id_from_keys(id: felt252) -> felt252; + + fn get(world: dojo::world::IWorldDispatcher, id: felt252) -> ModelWithShortStringNamespace; + + + fn get_v(world: dojo::world::IWorldDispatcher, id: felt252) -> Vec3; + + fn set_v(self: @ModelWithShortStringNamespace, world: dojo::world::IWorldDispatcher, value: Vec3); + +} +impl ModelWithStringNamespaceEntityDrop of core::traits::Drop::; +impl ModelWithStringNamespaceEntitySerde of core::serde::Serde:: { + fn serialize(self: @ModelWithStringNamespaceEntity, ref output: core::array::Array) { + core::serde::Serde::serialize(self.__id, ref output); + core::serde::Serde::serialize(self.v, ref output) + } + fn deserialize(ref serialized: core::array::Span) -> core::option::Option { + core::option::Option::Some(ModelWithStringNamespaceEntity { + __id: core::serde::Serde::deserialize(ref serialized)?, + v: core::serde::Serde::deserialize(ref serialized)?, + }) + } +} +trait ModelWithStringNamespaceEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> ModelWithStringNamespaceEntity; + + + fn get_v(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Vec3; + + fn set_v(self: @ModelWithStringNamespaceEntity, world: dojo::world::IWorldDispatcher, value: Vec3); + +} +trait ModelWithStringNamespaceTrait { + fn entity_id_from_keys(id: felt252) -> felt252; + + fn get(world: dojo::world::IWorldDispatcher, id: felt252) -> ModelWithStringNamespace; + + + fn get_v(world: dojo::world::IWorldDispatcher, id: felt252) -> Vec3; + + fn set_v(self: @ModelWithStringNamespace, world: dojo::world::IWorldDispatcher, value: Vec3); + +} +impl PositionEntityDrop of core::traits::Drop::; +impl PositionEntitySerde of core::serde::Serde:: { + fn serialize(self: @PositionEntity, ref output: core::array::Array) { + core::serde::Serde::serialize(self.__id, ref output); + core::serde::Serde::serialize(self.v, ref output) + } + fn deserialize(ref serialized: core::array::Span) -> core::option::Option { + core::option::Option::Some(PositionEntity { + __id: core::serde::Serde::deserialize(ref serialized)?, + v: core::serde::Serde::deserialize(ref serialized)?, + }) + } +} +trait PositionEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> PositionEntity; + + + fn get_v(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Vec3; + + fn set_v(self: @PositionEntity, world: dojo::world::IWorldDispatcher, value: Vec3); + +} +trait PositionTrait { + fn entity_id_from_keys(id: felt252) -> felt252; + + fn get(world: dojo::world::IWorldDispatcher, id: felt252) -> Position; + + + fn get_v(world: dojo::world::IWorldDispatcher, id: felt252) -> Vec3; + + fn set_v(self: @Position, world: dojo::world::IWorldDispatcher, value: Vec3); + +} +impl RolesEntityDrop of core::traits::Drop::; +impl RolesEntitySerde of core::serde::Serde:: { + fn serialize(self: @RolesEntity, ref output: core::array::Array) { + core::serde::Serde::serialize(self.__id, ref output); + core::serde::Serde::serialize(self.role_ids, ref output) + } + fn deserialize(ref serialized: core::array::Span) -> core::option::Option { + core::option::Option::Some(RolesEntity { + __id: core::serde::Serde::deserialize(ref serialized)?, + role_ids: core::serde::Serde::deserialize(ref serialized)?, + }) + } +} +trait RolesEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> RolesEntity; + + + fn get_role_ids(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Array; + + fn set_role_ids(self: @RolesEntity, world: dojo::world::IWorldDispatcher, value: Array); + +} +trait RolesTrait { + fn entity_id_from_keys() -> felt252; + + fn get(world: dojo::world::IWorldDispatcher, ) -> Roles; + + + fn get_role_ids(world: dojo::world::IWorldDispatcher, ) -> Array; + + fn set_role_ids(self: @Roles, world: dojo::world::IWorldDispatcher, value: Array); + +} +impl OnlyKeyModelEntityDrop of core::traits::Drop::; +impl OnlyKeyModelEntitySerde of core::serde::Serde:: { + fn serialize(self: @OnlyKeyModelEntity, ref output: core::array::Array) { + core::serde::Serde::serialize(self.__id, ref output) + } + fn deserialize(ref serialized: core::array::Span) -> core::option::Option { + core::option::Option::Some(OnlyKeyModelEntity { + __id: core::serde::Serde::deserialize(ref serialized)?, + }) + } +} +trait OnlyKeyModelEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> OnlyKeyModelEntity; + + +} +trait OnlyKeyModelTrait { + fn entity_id_from_keys(id: felt252) -> felt252; + + fn get(world: dojo::world::IWorldDispatcher, id: felt252) -> OnlyKeyModel; + + +} +impl U256KeyModelEntityDrop of core::traits::Drop::; +impl U256KeyModelEntitySerde of core::serde::Serde:: { + fn serialize(self: @U256KeyModelEntity, ref output: core::array::Array) { + core::serde::Serde::serialize(self.__id, ref output) + } + fn deserialize(ref serialized: core::array::Span) -> core::option::Option { + core::option::Option::Some(U256KeyModelEntity { + __id: core::serde::Serde::deserialize(ref serialized)?, + }) + } +} +trait U256KeyModelEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> U256KeyModelEntity; + + +} +trait U256KeyModelTrait { + fn entity_id_from_keys(id: u256) -> felt252; + + fn get(world: dojo::world::IWorldDispatcher, id: u256) -> U256KeyModel; + + +} +impl PlayerEntityDrop of core::traits::Drop::; +impl PlayerEntitySerde of core::serde::Serde:: { + fn serialize(self: @PlayerEntity, ref output: core::array::Array) { + core::serde::Serde::serialize(self.__id, ref output); + core::serde::Serde::serialize(self.name, ref output) + } + fn deserialize(ref serialized: core::array::Span) -> core::option::Option { + core::option::Option::Some(PlayerEntity { + __id: core::serde::Serde::deserialize(ref serialized)?, + name: core::serde::Serde::deserialize(ref serialized)?, + }) + } +} +trait PlayerEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> PlayerEntity; + + + fn get_name(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> felt252; + + fn set_name(self: @PlayerEntity, world: dojo::world::IWorldDispatcher, value: felt252); + +} +trait PlayerTrait { + fn entity_id_from_keys(game: felt252, player: ContractAddress) -> felt252; + + fn get(world: dojo::world::IWorldDispatcher, game: felt252, player: ContractAddress) -> Player; + + + fn get_name(world: dojo::world::IWorldDispatcher, game: felt252, player: ContractAddress) -> felt252; + + fn set_name(self: @Player, world: dojo::world::IWorldDispatcher, value: felt252); + +} +impl ModelWithSimpleArrayEntityDrop of core::traits::Drop::; +impl ModelWithSimpleArrayEntitySerde of core::serde::Serde:: { + fn serialize(self: @ModelWithSimpleArrayEntity, ref output: core::array::Array) { + core::serde::Serde::serialize(self.__id, ref output); + core::serde::Serde::serialize(self.x, ref output); + core::serde::Serde::serialize(self.y, ref output) + } + fn deserialize(ref serialized: core::array::Span) -> core::option::Option { + core::option::Option::Some(ModelWithSimpleArrayEntity { + __id: core::serde::Serde::deserialize(ref serialized)?, + x: core::serde::Serde::deserialize(ref serialized)?, + y: core::serde::Serde::deserialize(ref serialized)?, + }) + } +} +trait ModelWithSimpleArrayEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> ModelWithSimpleArrayEntity; + + + fn get_x(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> u16; + + fn set_x(self: @ModelWithSimpleArrayEntity, world: dojo::world::IWorldDispatcher, value: u16); + + fn get_y(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Array; + + fn set_y(self: @ModelWithSimpleArrayEntity, world: dojo::world::IWorldDispatcher, value: Array); + +} +trait ModelWithSimpleArrayTrait { + fn entity_id_from_keys(player: ContractAddress) -> felt252; + + fn get(world: dojo::world::IWorldDispatcher, player: ContractAddress) -> ModelWithSimpleArray; + + + fn get_x(world: dojo::world::IWorldDispatcher, player: ContractAddress) -> u16; + + fn set_x(self: @ModelWithSimpleArray, world: dojo::world::IWorldDispatcher, value: u16); + + fn get_y(world: dojo::world::IWorldDispatcher, player: ContractAddress) -> Array; + + fn set_y(self: @ModelWithSimpleArray, world: dojo::world::IWorldDispatcher, value: Array); + +} +impl ModelWithByteArrayEntityDrop of core::traits::Drop::; +impl ModelWithByteArrayEntitySerde of core::serde::Serde:: { + fn serialize(self: @ModelWithByteArrayEntity, ref output: core::array::Array) { + core::serde::Serde::serialize(self.__id, ref output); + core::serde::Serde::serialize(self.x, ref output); + core::serde::Serde::serialize(self.y, ref output) + } + fn deserialize(ref serialized: core::array::Span) -> core::option::Option { + core::option::Option::Some(ModelWithByteArrayEntity { + __id: core::serde::Serde::deserialize(ref serialized)?, + x: core::serde::Serde::deserialize(ref serialized)?, + y: core::serde::Serde::deserialize(ref serialized)?, + }) + } +} +trait ModelWithByteArrayEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> ModelWithByteArrayEntity; + + + fn get_x(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> u16; + + fn set_x(self: @ModelWithByteArrayEntity, world: dojo::world::IWorldDispatcher, value: u16); + + fn get_y(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> ByteArray; + + fn set_y(self: @ModelWithByteArrayEntity, world: dojo::world::IWorldDispatcher, value: ByteArray); + +} +trait ModelWithByteArrayTrait { + fn entity_id_from_keys(player: ContractAddress) -> felt252; + + fn get(world: dojo::world::IWorldDispatcher, player: ContractAddress) -> ModelWithByteArray; + + + fn get_x(world: dojo::world::IWorldDispatcher, player: ContractAddress) -> u16; + + fn set_x(self: @ModelWithByteArray, world: dojo::world::IWorldDispatcher, value: u16); + + fn get_y(world: dojo::world::IWorldDispatcher, player: ContractAddress) -> ByteArray; + + fn set_y(self: @ModelWithByteArray, world: dojo::world::IWorldDispatcher, value: ByteArray); + +} +impl ModelWithComplexArrayEntityDrop of core::traits::Drop::; +impl ModelWithComplexArrayEntitySerde of core::serde::Serde:: { + fn serialize(self: @ModelWithComplexArrayEntity, ref output: core::array::Array) { + core::serde::Serde::serialize(self.__id, ref output); + core::serde::Serde::serialize(self.x, ref output); + core::serde::Serde::serialize(self.y, ref output) + } + fn deserialize(ref serialized: core::array::Span) -> core::option::Option { + core::option::Option::Some(ModelWithComplexArrayEntity { + __id: core::serde::Serde::deserialize(ref serialized)?, + x: core::serde::Serde::deserialize(ref serialized)?, + y: core::serde::Serde::deserialize(ref serialized)?, + }) + } +} +trait ModelWithComplexArrayEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> ModelWithComplexArrayEntity; + + + fn get_x(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> u16; + + fn set_x(self: @ModelWithComplexArrayEntity, world: dojo::world::IWorldDispatcher, value: u16); + + fn get_y(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> Array; + + fn set_y(self: @ModelWithComplexArrayEntity, world: dojo::world::IWorldDispatcher, value: Array); + +} +trait ModelWithComplexArrayTrait { + fn entity_id_from_keys(player: ContractAddress) -> felt252; + + fn get(world: dojo::world::IWorldDispatcher, player: ContractAddress) -> ModelWithComplexArray; + + + fn get_x(world: dojo::world::IWorldDispatcher, player: ContractAddress) -> u16; + + fn set_x(self: @ModelWithComplexArray, world: dojo::world::IWorldDispatcher, value: u16); + + fn get_y(world: dojo::world::IWorldDispatcher, player: ContractAddress) -> Array; + + fn set_y(self: @ModelWithComplexArray, world: dojo::world::IWorldDispatcher, value: Array); + +} +impl ModelWithTupleEntityDrop of core::traits::Drop::; +impl ModelWithTupleEntitySerde of core::serde::Serde:: { + fn serialize(self: @ModelWithTupleEntity, ref output: core::array::Array) { + core::serde::Serde::serialize(self.__id, ref output); + core::serde::Serde::serialize(self.x, ref output); + core::serde::Serde::serialize(self.y, ref output) + } + fn deserialize(ref serialized: core::array::Span) -> core::option::Option { + core::option::Option::Some(ModelWithTupleEntity { + __id: core::serde::Serde::deserialize(ref serialized)?, + x: core::serde::Serde::deserialize(ref serialized)?, + y: core::serde::Serde::deserialize(ref serialized)?, + }) + } +} +trait ModelWithTupleEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> ModelWithTupleEntity; + + + fn get_x(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> u16; + + fn set_x(self: @ModelWithTupleEntity, world: dojo::world::IWorldDispatcher, value: u16); + + fn get_y(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> (u8, u16, u32); + + fn set_y(self: @ModelWithTupleEntity, world: dojo::world::IWorldDispatcher, value: (u8, u16, u32)); + +} +trait ModelWithTupleTrait { + fn entity_id_from_keys(player: ContractAddress) -> felt252; + + fn get(world: dojo::world::IWorldDispatcher, player: ContractAddress) -> ModelWithTuple; + + + fn get_x(world: dojo::world::IWorldDispatcher, player: ContractAddress) -> u16; + + fn set_x(self: @ModelWithTuple, world: dojo::world::IWorldDispatcher, value: u16); + + fn get_y(world: dojo::world::IWorldDispatcher, player: ContractAddress) -> (u8, u16, u32); + + fn set_y(self: @ModelWithTuple, world: dojo::world::IWorldDispatcher, value: (u8, u16, u32)); + +} +impl ModelWithTupleNoPrimitivesEntityDrop of core::traits::Drop::; +impl ModelWithTupleNoPrimitivesEntitySerde of core::serde::Serde:: { + fn serialize(self: @ModelWithTupleNoPrimitivesEntity, ref output: core::array::Array) { + core::serde::Serde::serialize(self.__id, ref output); + core::serde::Serde::serialize(self.x, ref output); + core::serde::Serde::serialize(self.y, ref output) + } + fn deserialize(ref serialized: core::array::Span) -> core::option::Option { + core::option::Option::Some(ModelWithTupleNoPrimitivesEntity { + __id: core::serde::Serde::deserialize(ref serialized)?, + x: core::serde::Serde::deserialize(ref serialized)?, + y: core::serde::Serde::deserialize(ref serialized)?, + }) + } +} +trait ModelWithTupleNoPrimitivesEntityTrait { + fn get(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> ModelWithTupleNoPrimitivesEntity; + + + fn get_x(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> u16; + + fn set_x(self: @ModelWithTupleNoPrimitivesEntity, world: dojo::world::IWorldDispatcher, value: u16); + + fn get_y(world: dojo::world::IWorldDispatcher, entity_id: felt252) -> (u8, Vec3, u32); + + fn set_y(self: @ModelWithTupleNoPrimitivesEntity, world: dojo::world::IWorldDispatcher, value: (u8, Vec3, u32)); + +} +trait ModelWithTupleNoPrimitivesTrait { + fn entity_id_from_keys(player: ContractAddress) -> felt252; + + fn get(world: dojo::world::IWorldDispatcher, player: ContractAddress) -> ModelWithTupleNoPrimitives; + + + fn get_x(world: dojo::world::IWorldDispatcher, player: ContractAddress) -> u16; + + fn set_x(self: @ModelWithTupleNoPrimitives, world: dojo::world::IWorldDispatcher, value: u16); + + fn get_y(world: dojo::world::IWorldDispatcher, player: ContractAddress) -> (u8, Vec3, u32); + + fn set_y(self: @ModelWithTupleNoPrimitives, world: dojo::world::IWorldDispatcher, value: (u8, Vec3, u32)); + +} + +//! > expected_diagnostics +error: A Dojo model must have zero or one dojo::model attribute. + --> test_src/lib.cairo:1:1 +#[dojo::model(version: 0)] +^************************^ + +error: Too many 'version' attributes for dojo::model + --> test_src/lib.cairo:9:1 +#[dojo::model(version: 0, version: 0)] +^************************************^ + +error: The argument 'version' of dojo::model must be an integer + --> test_src/lib.cairo:16:24 +#[dojo::model(version: hello)] ^***^ error: Unexpected argument 'version' for dojo::model @@ -4818,12 +11247,12 @@ error: Model must define at least one member that is not a key struct OnlyKeyModel { ^**********^ -error: Model must define at least one member that is not a key - --> test_src/lib.cairo:98:8 -struct U256KeyModel { - ^**********^ - error: Key is only supported for core types that are 1 felt long once serialized. `u256` is a struct of 2 u128, hence not supported. + --> test_src/lib.cairo:100:5 + id: u256 + ^^ + +error: Model must define at least one member that is not a key --> test_src/lib.cairo:98:8 struct U256KeyModel { ^**********^ diff --git a/crates/dojo-lang/src/semantics/test_data/get b/crates/dojo-lang/src/semantics/test_data/get index 5f90c0d359..13e45b47a7 100644 --- a/crates/dojo-lang/src/semantics/test_data/get +++ b/crates/dojo-lang/src/semantics/test_data/get @@ -194,21 +194,6 @@ Block( ), }, ), - Let( - StatementLet { - pattern: Variable( - __Health_layout__, - ), - expr: FunctionCall( - ExprFunctionCall { - function: ?7::layout, - args: [], - coupon_arg: None, - ty: dojo::database::introspect::Layout, - }, - ), - }, - ), Let( StatementLet { pattern: Variable( @@ -216,7 +201,7 @@ Block( ), expr: FunctionCall( ExprFunctionCall { - function: ?8::entity, + function: ?7::get, args: [ Value( Var( @@ -228,11 +213,6 @@ Block( LocalVarId(test::__get_macro_keys__), ), ), - Value( - Var( - LocalVarId(test::__Health_layout__), - ), - ), ], coupon_arg: None, ty: test::Health, diff --git a/crates/dojo-lang/src/semantics/test_data/set b/crates/dojo-lang/src/semantics/test_data/set index d41133d396..03cd1da1b9 100644 --- a/crates/dojo-lang/src/semantics/test_data/set +++ b/crates/dojo-lang/src/semantics/test_data/set @@ -119,95 +119,21 @@ Block( StatementExpr { expr: FunctionCall( ExprFunctionCall { - function: dojo::world::IWorldDispatcherImpl::set_entity, + function: ?6::set, args: [ Value( - Var( - LocalVarId(test::world), - ), - ), - Value( - FunctionCall( - ExprFunctionCall { - function: ?7::instance_selector, - args: [ - Value( - Snapshot( - ExprSnapshot { - inner: Var( - LocalVarId(test::__set_model_instance__), - ), - ty: @test::Health, - }, - ), - ), - ], - coupon_arg: None, - ty: core::felt252, - }, - ), - ), - Value( - FunctionCall( - ExprFunctionCall { - function: ?8::keys, - args: [ - Value( - Snapshot( - ExprSnapshot { - inner: Var( - LocalVarId(test::__set_model_instance__), - ), - ty: @test::Health, - }, - ), - ), - ], - coupon_arg: None, - ty: core::array::Span::, - }, - ), - ), - Value( - FunctionCall( - ExprFunctionCall { - function: ?9::values, - args: [ - Value( - Snapshot( - ExprSnapshot { - inner: Var( - LocalVarId(test::__set_model_instance__), - ), - ty: @test::Health, - }, - ), - ), - ], - coupon_arg: None, - ty: core::array::Span::, + Snapshot( + ExprSnapshot { + inner: Var( + LocalVarId(test::__set_model_instance__), + ), + ty: @test::Health, }, ), ), Value( - FunctionCall( - ExprFunctionCall { - function: ?10::instance_layout, - args: [ - Value( - Snapshot( - ExprSnapshot { - inner: Var( - LocalVarId(test::__set_model_instance__), - ), - ty: @test::Health, - }, - ), - ), - ], - coupon_arg: None, - ty: dojo::database::introspect::Layout, - }, + Var( + LocalVarId(test::world), ), ), ], diff --git a/crates/dojo-world/src/contracts/abi/world.rs b/crates/dojo-world/src/contracts/abi/world.rs index f681f1ab97..05a3c18707 100644 --- a/crates/dojo-world/src/contracts/abi/world.rs +++ b/crates/dojo-world/src/contracts/abi/world.rs @@ -52,6 +52,24 @@ abigen!( } ] }, + { + "type": "enum", + "name": "dojo::world::ModelIndex", + "variants": [ + { + "name": "Keys", + "type": "core::array::Span::" + }, + { + "name": "Id", + "type": "core::felt252" + }, + { + "name": "MemberId", + "type": "(core::felt252, core::felt252)" + } + ] + }, { "type": "struct", "name": "core::array::Span::", @@ -288,12 +306,12 @@ abigen!( "name": "entity", "inputs": [ { - "name": "model", + "name": "model_selector", "type": "core::felt252" }, { - "name": "keys", - "type": "core::array::Span::" + "name": "index", + "type": "dojo::world::ModelIndex" }, { "name": "layout", @@ -312,12 +330,12 @@ abigen!( "name": "set_entity", "inputs": [ { - "name": "model", + "name": "model_selector", "type": "core::felt252" }, { - "name": "keys", - "type": "core::array::Span::" + "name": "index", + "type": "dojo::world::ModelIndex" }, { "name": "values", @@ -336,12 +354,12 @@ abigen!( "name": "delete_entity", "inputs": [ { - "name": "model", + "name": "model_selector", "type": "core::felt252" }, { - "name": "keys", - "type": "core::array::Span::" + "name": "index", + "type": "dojo::world::ModelIndex" }, { "name": "layout", @@ -491,7 +509,7 @@ abigen!( "name": "can_write_model", "inputs": [ { - "name": "model_id", + "name": "model_selector", "type": "core::felt252" }, { @@ -907,7 +925,7 @@ abigen!( }, { "type": "event", - "name": "dojo::world::world::StoreDelRecord", + "name": "dojo::world::world::StoreUpdateRecord", "kind": "struct", "members": [ { @@ -916,12 +934,34 @@ abigen!( "kind": "data" }, { - "name": "keys", + "name": "entity_id", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "values", "type": "core::array::Span::", "kind": "data" } ] }, + { + "type": "event", + "name": "dojo::world::world::StoreDelRecord", + "kind": "struct", + "members": [ + { + "name": "table", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "entity_id", + "type": "core::felt252", + "kind": "data" + } + ] + }, { "type": "event", "name": "dojo::world::world::WriterUpdated", @@ -1081,6 +1121,11 @@ abigen!( "type": "dojo::world::world::StoreSetRecord", "kind": "nested" }, + { + "name": "StoreUpdateRecord", + "type": "dojo::world::world::StoreUpdateRecord", + "kind": "nested" + }, { "name": "StoreDelRecord", "type": "dojo::world::world::StoreDelRecord", diff --git a/crates/dojo-world/src/contracts/model.rs b/crates/dojo-world/src/contracts/model.rs index de38198885..1026a2c19f 100644 --- a/crates/dojo-world/src/contracts/model.rs +++ b/crates/dojo-world/src/contracts/model.rs @@ -25,6 +25,9 @@ pub mod abigen { pub mod model { pub use crate::contracts::abi::model::*; } + pub mod world { + pub use crate::contracts::abi::world::*; + } } #[derive(Debug, thiserror::Error)] @@ -126,7 +129,11 @@ where let raw_layout = self.model_reader.layout().raw_call().await?; let layout = Layout::cairo_deserialize(raw_layout.as_slice(), 0)?; - Ok(self.world_reader.entity(&self.selector(), &keys.to_vec(), &layout).call().await?) + Ok(self + .world_reader + .entity(&self.selector(), &abigen::world::ModelIndex::Keys(keys.to_vec()), &layout) + .call() + .await?) } pub async fn entity(&self, keys: &[Felt]) -> Result { diff --git a/crates/dojo-world/src/contracts/naming.rs b/crates/dojo-world/src/contracts/naming.rs index d910e98837..5dbd4e80f9 100644 --- a/crates/dojo-world/src/contracts/naming.rs +++ b/crates/dojo-world/src/contracts/naming.rs @@ -57,8 +57,8 @@ pub fn get_filename_from_tag(tag: &str) -> String { format!("{tag}{TAG_SEPARATOR}{selector}") } -pub fn compute_bytearray_hash(namespace: &str) -> Felt { - let ba = ByteArray::from_string(namespace).unwrap(); +pub fn compute_bytearray_hash(value: &str) -> Felt { + let ba = ByteArray::from_string(value).unwrap(); poseidon_hash_many(&ByteArray::cairo_serialize(&ba)) } diff --git a/crates/sozo/ops/src/events.rs b/crates/sozo/ops/src/events.rs index 4092613eb0..cd182b3df7 100644 --- a/crates/sozo/ops/src/events.rs +++ b/crates/sozo/ops/src/events.rs @@ -279,7 +279,7 @@ mod tests { let result = extract_events(&manifest, &project_dir, &target_dir).unwrap(); // we are just collecting all events from manifest file so just verifying count should work - assert_eq!(result.len(), 16); + assert_eq!(result.len(), 17); } #[test] diff --git a/crates/torii/types-test/src/contracts.cairo b/crates/torii/types-test/src/contracts.cairo index df0ef8be39..88a24731ce 100644 --- a/crates/torii/types-test/src/contracts.cairo +++ b/crates/torii/types-test/src/contracts.cairo @@ -10,7 +10,7 @@ trait IRecords { mod records { use starknet::{ContractAddress, get_caller_address}; use types_test::models::{ - Record, RecordSibling, Subrecord, Nested, NestedMore, NestedMost, Depth + Record, RecordTrait, RecordSibling, RecordSiblingTrait, Subrecord, SubrecordTrait, Nested, NestedMore, NestedMost, Depth }; use types_test::{seed, random}; use super::IRecords; diff --git a/examples/spawn-and-move/Scarb.toml b/examples/spawn-and-move/Scarb.toml index c5c1f0a06c..72c8bfdb64 100644 --- a/examples/spawn-and-move/Scarb.toml +++ b/examples/spawn-and-move/Scarb.toml @@ -33,7 +33,27 @@ rpc_url = "http://localhost:5050/" # Default account for katana with seed = 0 account_address = "0x6162896d1d7ab204c7ccac6dd5f8e9e7c25ecd5ae4fcb4ad32e57786bb46e03" private_key = "0x1800000000300000180000000000030000000000003006001800006600" -world_address = "0x504b804eeac62e68d12dc030e56b8f62cb047950c346e60a974da02795f6aba" +world_address = "0x6d95c696211b4453e1f4b1b2dc9fb9d91602d4a7a1550567362bd9b8bcd9a82" + +# `release` profile +# +# for now configurations in `tool` are not merged recursively so to override +# `skip_migration` we need to redefine the whole `tool.dojo` table +[profile.release] + +[profile.release.tool.dojo.world] +description = "example world" +name = "example" +seed = "dojo_examples" +namespace = "dojo_examples" + +[profile.release.tool.dojo.env] +rpc_url = "http://localhost:5050/" + +# Default account for katana with seed = 0 +account_address = "0x6162896d1d7ab204c7ccac6dd5f8e9e7c25ecd5ae4fcb4ad32e57786bb46e03" +private_key = "0x1800000000300000180000000000030000000000003006001800006600" +world_address = "0x6d95c696211b4453e1f4b1b2dc9fb9d91602d4a7a1550567362bd9b8bcd9a82" [profile.release.tool.dojo] # for more info on how `merge-strategy` works see: diff --git a/examples/spawn-and-move/manifests/dev/base/abis/contracts/dojo_examples-actions-40b6994c.json b/examples/spawn-and-move/manifests/dev/base/abis/contracts/dojo_examples-actions-40b6994c.json index a8654af001..c2e9d96d5a 100644 --- a/examples/spawn-and-move/manifests/dev/base/abis/contracts/dojo_examples-actions-40b6994c.json +++ b/examples/spawn-and-move/manifests/dev/base/abis/contracts/dojo_examples-actions-40b6994c.json @@ -274,6 +274,30 @@ ], "state_mutability": "view" }, + { + "type": "function", + "name": "update_player_name", + "inputs": [ + { + "name": "name", + "type": "core::byte_array::ByteArray" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "update_player_name_value", + "inputs": [ + { + "name": "name", + "type": "core::byte_array::ByteArray" + } + ], + "outputs": [], + "state_mutability": "external" + }, { "type": "function", "name": "reset_player_config", diff --git a/examples/spawn-and-move/manifests/dev/base/abis/dojo-world.json b/examples/spawn-and-move/manifests/dev/base/abis/dojo-world.json index 0e5e96210e..6dd9a18e1a 100644 --- a/examples/spawn-and-move/manifests/dev/base/abis/dojo-world.json +++ b/examples/spawn-and-move/manifests/dev/base/abis/dojo-world.json @@ -46,6 +46,24 @@ } ] }, + { + "type": "enum", + "name": "dojo::world::ModelIndex", + "variants": [ + { + "name": "Keys", + "type": "core::array::Span::" + }, + { + "name": "Id", + "type": "core::felt252" + }, + { + "name": "MemberId", + "type": "(core::felt252, core::felt252)" + } + ] + }, { "type": "struct", "name": "core::array::Span::", @@ -282,12 +300,12 @@ "name": "entity", "inputs": [ { - "name": "model", + "name": "model_selector", "type": "core::felt252" }, { - "name": "keys", - "type": "core::array::Span::" + "name": "index", + "type": "dojo::world::ModelIndex" }, { "name": "layout", @@ -306,12 +324,12 @@ "name": "set_entity", "inputs": [ { - "name": "model", + "name": "model_selector", "type": "core::felt252" }, { - "name": "keys", - "type": "core::array::Span::" + "name": "index", + "type": "dojo::world::ModelIndex" }, { "name": "values", @@ -330,12 +348,12 @@ "name": "delete_entity", "inputs": [ { - "name": "model", + "name": "model_selector", "type": "core::felt252" }, { - "name": "keys", - "type": "core::array::Span::" + "name": "index", + "type": "dojo::world::ModelIndex" }, { "name": "layout", @@ -485,7 +503,7 @@ "name": "can_write_model", "inputs": [ { - "name": "model_id", + "name": "model_selector", "type": "core::felt252" }, { @@ -901,7 +919,7 @@ }, { "type": "event", - "name": "dojo::world::world::StoreDelRecord", + "name": "dojo::world::world::StoreUpdateRecord", "kind": "struct", "members": [ { @@ -910,12 +928,34 @@ "kind": "data" }, { - "name": "keys", + "name": "entity_id", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "values", "type": "core::array::Span::", "kind": "data" } ] }, + { + "type": "event", + "name": "dojo::world::world::StoreDelRecord", + "kind": "struct", + "members": [ + { + "name": "table", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "entity_id", + "type": "core::felt252", + "kind": "data" + } + ] + }, { "type": "event", "name": "dojo::world::world::WriterUpdated", @@ -1075,6 +1115,11 @@ "type": "dojo::world::world::StoreSetRecord", "kind": "nested" }, + { + "name": "StoreUpdateRecord", + "type": "dojo::world::world::StoreUpdateRecord", + "kind": "nested" + }, { "name": "StoreDelRecord", "type": "dojo::world::world::StoreDelRecord", diff --git a/examples/spawn-and-move/manifests/dev/base/contracts/dojo_examples-actions-40b6994c.toml b/examples/spawn-and-move/manifests/dev/base/contracts/dojo_examples-actions-40b6994c.toml index 9bd796836c..8a44f07d45 100644 --- a/examples/spawn-and-move/manifests/dev/base/contracts/dojo_examples-actions-40b6994c.toml +++ b/examples/spawn-and-move/manifests/dev/base/contracts/dojo_examples-actions-40b6994c.toml @@ -1,6 +1,6 @@ kind = "DojoContract" -class_hash = "0x1843e2e8c174c087de5ebaf04eee196eb0526b6345ad5ac3a6055d4e0dd1363" -original_class_hash = "0x1843e2e8c174c087de5ebaf04eee196eb0526b6345ad5ac3a6055d4e0dd1363" +class_hash = "0x288e853c84bde01bdbfbd8b8ffe0ff91ebbce90891e5d300f3395abbb50094d" +original_class_hash = "0x288e853c84bde01bdbfbd8b8ffe0ff91ebbce90891e5d300f3395abbb50094d" base_class_hash = "0x0" abi = "manifests/dev/base/abis/contracts/dojo_examples-actions-40b6994c.json" reads = [] diff --git a/examples/spawn-and-move/manifests/dev/base/contracts/dojo_examples-mock_token-31599eb2.toml b/examples/spawn-and-move/manifests/dev/base/contracts/dojo_examples-mock_token-31599eb2.toml index 137baf0aaa..295d2d78f1 100644 --- a/examples/spawn-and-move/manifests/dev/base/contracts/dojo_examples-mock_token-31599eb2.toml +++ b/examples/spawn-and-move/manifests/dev/base/contracts/dojo_examples-mock_token-31599eb2.toml @@ -1,6 +1,6 @@ kind = "DojoContract" -class_hash = "0x97cd4fb3acfe9e6a024589ea34db2fc587586d699ef3732ce627e1771158ef" -original_class_hash = "0x97cd4fb3acfe9e6a024589ea34db2fc587586d699ef3732ce627e1771158ef" +class_hash = "0x761d18a3557d98b3962ebb2c9ddae89ad586ce81de7e86c5fd1e1b4f9d0028" +original_class_hash = "0x761d18a3557d98b3962ebb2c9ddae89ad586ce81de7e86c5fd1e1b4f9d0028" base_class_hash = "0x0" abi = "manifests/dev/base/abis/contracts/dojo_examples-mock_token-31599eb2.json" reads = [] diff --git a/examples/spawn-and-move/manifests/dev/base/dojo-world.toml b/examples/spawn-and-move/manifests/dev/base/dojo-world.toml index 83a7a20228..03f06ebea5 100644 --- a/examples/spawn-and-move/manifests/dev/base/dojo-world.toml +++ b/examples/spawn-and-move/manifests/dev/base/dojo-world.toml @@ -1,6 +1,6 @@ kind = "Class" -class_hash = "0x210dd8e484e5555dc74a4a600b17878fc108911719b04139309acc874160c51" -original_class_hash = "0x210dd8e484e5555dc74a4a600b17878fc108911719b04139309acc874160c51" +class_hash = "0x2bcf11feac030c5ec81496dfc73ae256568c5b7518f8542e25dd0e42938de7e" +original_class_hash = "0x2bcf11feac030c5ec81496dfc73ae256568c5b7518f8542e25dd0e42938de7e" abi = "manifests/dev/base/abis/dojo-world.json" tag = "dojo-world" manifest_name = "dojo-world" diff --git a/examples/spawn-and-move/manifests/dev/deployment/abis/contracts/dojo_examples-actions-40b6994c.json b/examples/spawn-and-move/manifests/dev/deployment/abis/contracts/dojo_examples-actions-40b6994c.json index 16ee68e05e..c2e9d96d5a 100644 --- a/examples/spawn-and-move/manifests/dev/deployment/abis/contracts/dojo_examples-actions-40b6994c.json +++ b/examples/spawn-and-move/manifests/dev/deployment/abis/contracts/dojo_examples-actions-40b6994c.json @@ -274,6 +274,30 @@ ], "state_mutability": "view" }, + { + "type": "function", + "name": "update_player_name", + "inputs": [ + { + "name": "name", + "type": "core::byte_array::ByteArray" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "update_player_name_value", + "inputs": [ + { + "name": "name", + "type": "core::byte_array::ByteArray" + } + ], + "outputs": [], + "state_mutability": "external" + }, { "type": "function", "name": "reset_player_config", @@ -296,6 +320,18 @@ ], "outputs": [], "state_mutability": "external" + }, + { + "type": "function", + "name": "call_something", + "inputs": [ + { + "name": "something_address", + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "outputs": [], + "state_mutability": "view" } ] }, diff --git a/examples/spawn-and-move/manifests/dev/deployment/abis/dojo-world.json b/examples/spawn-and-move/manifests/dev/deployment/abis/dojo-world.json index 0e5e96210e..6dd9a18e1a 100644 --- a/examples/spawn-and-move/manifests/dev/deployment/abis/dojo-world.json +++ b/examples/spawn-and-move/manifests/dev/deployment/abis/dojo-world.json @@ -46,6 +46,24 @@ } ] }, + { + "type": "enum", + "name": "dojo::world::ModelIndex", + "variants": [ + { + "name": "Keys", + "type": "core::array::Span::" + }, + { + "name": "Id", + "type": "core::felt252" + }, + { + "name": "MemberId", + "type": "(core::felt252, core::felt252)" + } + ] + }, { "type": "struct", "name": "core::array::Span::", @@ -282,12 +300,12 @@ "name": "entity", "inputs": [ { - "name": "model", + "name": "model_selector", "type": "core::felt252" }, { - "name": "keys", - "type": "core::array::Span::" + "name": "index", + "type": "dojo::world::ModelIndex" }, { "name": "layout", @@ -306,12 +324,12 @@ "name": "set_entity", "inputs": [ { - "name": "model", + "name": "model_selector", "type": "core::felt252" }, { - "name": "keys", - "type": "core::array::Span::" + "name": "index", + "type": "dojo::world::ModelIndex" }, { "name": "values", @@ -330,12 +348,12 @@ "name": "delete_entity", "inputs": [ { - "name": "model", + "name": "model_selector", "type": "core::felt252" }, { - "name": "keys", - "type": "core::array::Span::" + "name": "index", + "type": "dojo::world::ModelIndex" }, { "name": "layout", @@ -485,7 +503,7 @@ "name": "can_write_model", "inputs": [ { - "name": "model_id", + "name": "model_selector", "type": "core::felt252" }, { @@ -901,7 +919,7 @@ }, { "type": "event", - "name": "dojo::world::world::StoreDelRecord", + "name": "dojo::world::world::StoreUpdateRecord", "kind": "struct", "members": [ { @@ -910,12 +928,34 @@ "kind": "data" }, { - "name": "keys", + "name": "entity_id", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "values", "type": "core::array::Span::", "kind": "data" } ] }, + { + "type": "event", + "name": "dojo::world::world::StoreDelRecord", + "kind": "struct", + "members": [ + { + "name": "table", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "entity_id", + "type": "core::felt252", + "kind": "data" + } + ] + }, { "type": "event", "name": "dojo::world::world::WriterUpdated", @@ -1075,6 +1115,11 @@ "type": "dojo::world::world::StoreSetRecord", "kind": "nested" }, + { + "name": "StoreUpdateRecord", + "type": "dojo::world::world::StoreUpdateRecord", + "kind": "nested" + }, { "name": "StoreDelRecord", "type": "dojo::world::world::StoreDelRecord", diff --git a/examples/spawn-and-move/manifests/dev/deployment/abis/models/dojo_examples-DirectionsAvailable-22b3dd08.json b/examples/spawn-and-move/manifests/dev/deployment/abis/models/dojo_examples-DirectionsAvailable-22b3dd08.json new file mode 100644 index 0000000000..850147f48e --- /dev/null +++ b/examples/spawn-and-move/manifests/dev/deployment/abis/models/dojo_examples-DirectionsAvailable-22b3dd08.json @@ -0,0 +1,433 @@ +[ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::database::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::database::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::database::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::IModel", + "items": [ + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "tag", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "directions_availableImpl", + "interface_name": "dojo_examples::models::Idirections_available" + }, + { + "type": "enum", + "name": "dojo_examples::models::Direction", + "variants": [ + { + "name": "None", + "type": "()" + }, + { + "name": "Left", + "type": "()" + }, + { + "name": "Right", + "type": "()" + }, + { + "name": "Up", + "type": "()" + }, + { + "name": "Down", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "dojo_examples::models::DirectionsAvailable", + "members": [ + { + "name": "player", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "directions", + "type": "core::array::Array::" + } + ] + }, + { + "type": "interface", + "name": "dojo_examples::models::Idirections_available", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "dojo_examples::models::DirectionsAvailable" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::models::directions_available::Event", + "kind": "enum", + "variants": [] + } +] \ No newline at end of file diff --git a/examples/spawn-and-move/manifests/dev/deployment/manifest.json b/examples/spawn-and-move/manifests/dev/deployment/manifest.json index 99501691fc..c07640232d 100644 --- a/examples/spawn-and-move/manifests/dev/deployment/manifest.json +++ b/examples/spawn-and-move/manifests/dev/deployment/manifest.json @@ -1,8 +1,8 @@ { "world": { "kind": "WorldContract", - "class_hash": "0x210dd8e484e5555dc74a4a600b17878fc108911719b04139309acc874160c51", - "original_class_hash": "0x210dd8e484e5555dc74a4a600b17878fc108911719b04139309acc874160c51", + "class_hash": "0x2bcf11feac030c5ec81496dfc73ae256568c5b7518f8542e25dd0e42938de7e", + "original_class_hash": "0x2bcf11feac030c5ec81496dfc73ae256568c5b7518f8542e25dd0e42938de7e", "abi": [ { "type": "impl", @@ -51,6 +51,24 @@ } ] }, + { + "type": "enum", + "name": "dojo::world::ModelIndex", + "variants": [ + { + "name": "Keys", + "type": "core::array::Span::" + }, + { + "name": "Id", + "type": "core::felt252" + }, + { + "name": "MemberId", + "type": "(core::felt252, core::felt252)" + } + ] + }, { "type": "struct", "name": "core::array::Span::", @@ -287,12 +305,12 @@ "name": "entity", "inputs": [ { - "name": "model", + "name": "model_selector", "type": "core::felt252" }, { - "name": "keys", - "type": "core::array::Span::" + "name": "index", + "type": "dojo::world::ModelIndex" }, { "name": "layout", @@ -311,12 +329,12 @@ "name": "set_entity", "inputs": [ { - "name": "model", + "name": "model_selector", "type": "core::felt252" }, { - "name": "keys", - "type": "core::array::Span::" + "name": "index", + "type": "dojo::world::ModelIndex" }, { "name": "values", @@ -335,12 +353,12 @@ "name": "delete_entity", "inputs": [ { - "name": "model", + "name": "model_selector", "type": "core::felt252" }, { - "name": "keys", - "type": "core::array::Span::" + "name": "index", + "type": "dojo::world::ModelIndex" }, { "name": "layout", @@ -490,7 +508,7 @@ "name": "can_write_model", "inputs": [ { - "name": "model_id", + "name": "model_selector", "type": "core::felt252" }, { @@ -906,7 +924,7 @@ }, { "type": "event", - "name": "dojo::world::world::StoreDelRecord", + "name": "dojo::world::world::StoreUpdateRecord", "kind": "struct", "members": [ { @@ -915,12 +933,34 @@ "kind": "data" }, { - "name": "keys", + "name": "entity_id", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "values", "type": "core::array::Span::", "kind": "data" } ] }, + { + "type": "event", + "name": "dojo::world::world::StoreDelRecord", + "kind": "struct", + "members": [ + { + "name": "table", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "entity_id", + "type": "core::felt252", + "kind": "data" + } + ] + }, { "type": "event", "name": "dojo::world::world::WriterUpdated", @@ -1080,6 +1120,11 @@ "type": "dojo::world::world::StoreSetRecord", "kind": "nested" }, + { + "name": "StoreUpdateRecord", + "type": "dojo::world::world::StoreUpdateRecord", + "kind": "nested" + }, { "name": "StoreDelRecord", "type": "dojo::world::world::StoreDelRecord", @@ -1108,8 +1153,8 @@ ] } ], - "address": "0x504b804eeac62e68d12dc030e56b8f62cb047950c346e60a974da02795f6aba", - "transaction_hash": "0x65168705b42b38a0b9e290dfb079e023fa1960febb9fd7069fce5e369e3b56f", + "address": "0x6d95c696211b4453e1f4b1b2dc9fb9d91602d4a7a1550567362bd9b8bcd9a82", + "transaction_hash": "0x3290c6ba1226811dcf2c971b005dffd18965e93d0c11f9d8f2ae853d6890ab4", "block_number": 3, "seed": "dojo_examples", "metadata": { @@ -1129,9 +1174,9 @@ "contracts": [ { "kind": "DojoContract", - "address": "0x2e85647f570d2a4abdffdd668823702548d20d1d6aaef74b6a4eb9670a32798", - "class_hash": "0x647694c15fff8476c82ea146d0dbdbbb17d3425d5ba05a7320e4322f916df1d", - "original_class_hash": "0x647694c15fff8476c82ea146d0dbdbbb17d3425d5ba05a7320e4322f916df1d", + "address": "0x1a0504af4ffec1a748ae115e8d36b8cd7913298308ae4eb39e1eee8fc19d516", + "class_hash": "0x288e853c84bde01bdbfbd8b8ffe0ff91ebbce90891e5d300f3395abbb50094d", + "original_class_hash": "0x288e853c84bde01bdbfbd8b8ffe0ff91ebbce90891e5d300f3395abbb50094d", "base_class_hash": "0x26a4f5d2d9638877a2648297339275df5eaab0adb3cdf0010887c2dbf2be4", "abi": [ { @@ -1409,6 +1454,30 @@ ], "state_mutability": "view" }, + { + "type": "function", + "name": "update_player_name", + "inputs": [ + { + "name": "name", + "type": "core::byte_array::ByteArray" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "update_player_name_value", + "inputs": [ + { + "name": "name", + "type": "core::byte_array::ByteArray" + } + ], + "outputs": [], + "state_mutability": "external" + }, { "type": "function", "name": "reset_player_config", @@ -1431,6 +1500,18 @@ ], "outputs": [], "state_mutability": "external" + }, + { + "type": "function", + "name": "call_something", + "inputs": [ + { + "name": "something_address", + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "outputs": [], + "state_mutability": "view" } ] }, @@ -1524,9 +1605,9 @@ }, { "kind": "DojoContract", - "address": "0x6a06eb156f956f1691bce4a4573c97b1a5f08d3bfa65fc25c4ed4b55d3e61a1", - "class_hash": "0x97cd4fb3acfe9e6a024589ea34db2fc587586d699ef3732ce627e1771158ef", - "original_class_hash": "0x97cd4fb3acfe9e6a024589ea34db2fc587586d699ef3732ce627e1771158ef", + "address": "0x5a8f0aacc5fa9b30fdffee908d7e6093dedda92ad6deefff31aa06b473312e8", + "class_hash": "0x761d18a3557d98b3962ebb2c9ddae89ad586ce81de7e86c5fd1e1b4f9d0028", + "original_class_hash": "0x761d18a3557d98b3962ebb2c9ddae89ad586ce81de7e86c5fd1e1b4f9d0028", "base_class_hash": "0x26a4f5d2d9638877a2648297339275df5eaab0adb3cdf0010887c2dbf2be4", "abi": [ { @@ -1743,7 +1824,7 @@ }, { "kind": "DojoContract", - "address": "0x6359537114e0a62c63f52f2fb3c0e6241c9a2fcbd9dc9df221c867662aa31e9", + "address": "0x5958b21ca9debb6bf444aebefef92305d3b0f3fd39e20097161282078666873", "class_hash": "0x479bfb12dcba5398d77303e7a665fc3fedb16f2d7f9cb1f5d7e2beb3b7e2ba7", "original_class_hash": "0x479bfb12dcba5398d77303e7a665fc3fedb16f2d7f9cb1f5d7e2beb3b7e2ba7", "base_class_hash": "0x26a4f5d2d9638877a2648297339275df5eaab0adb3cdf0010887c2dbf2be4", @@ -1976,6 +2057,243 @@ ], "tag": "dojo_examples-others", "manifest_name": "dojo_examples-others-61de2c18" + }, + { + "kind": "DojoContract", + "address": "0x20cf302cf7c93c871d2ec1bc0d4256e926a54b59ddbc3a6746f2b3430ab6f31", + "class_hash": "0x2633dd37ecb3e273b309a3339da5dc820f2b77d4da474d7215952a1b60950dc", + "original_class_hash": "0x2633dd37ecb3e273b309a3339da5dc820f2b77d4da474d7215952a1b60950dc", + "base_class_hash": "0x26a4f5d2d9638877a2648297339275df5eaab0adb3cdf0010887c2dbf2be4", + "abi": [ + { + "type": "impl", + "name": "ContractImpl", + "interface_name": "dojo::contract::IContract" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "interface", + "name": "dojo::contract::IContract", + "items": [ + { + "type": "function", + "name": "contract_name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "tag", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "namespace_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "WorldProviderImpl", + "interface_name": "dojo::world::IWorldProvider" + }, + { + "type": "struct", + "name": "dojo::world::IWorldDispatcher", + "members": [ + { + "name": "contract_address", + "type": "core::starknet::contract_address::ContractAddress" + } + ] + }, + { + "type": "interface", + "name": "dojo::world::IWorldProvider", + "items": [ + { + "type": "function", + "name": "world", + "inputs": [], + "outputs": [ + { + "type": "dojo::world::IWorldDispatcher" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "ISomethingImpl", + "interface_name": "dojo_examples::something::ISomething" + }, + { + "type": "interface", + "name": "dojo_examples::something::ISomething", + "items": [ + { + "type": "function", + "name": "something", + "inputs": [], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "IDojoInitImpl", + "interface_name": "dojo_examples::something::something::IDojoInit" + }, + { + "type": "interface", + "name": "dojo_examples::something::something::IDojoInit", + "items": [ + { + "type": "function", + "name": "dojo_init", + "inputs": [], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "UpgradableImpl", + "interface_name": "dojo::components::upgradeable::IUpgradeable" + }, + { + "type": "interface", + "name": "dojo::components::upgradeable::IUpgradeable", + "items": [ + { + "type": "function", + "name": "upgrade", + "inputs": [ + { + "name": "new_class_hash", + "type": "core::starknet::class_hash::ClassHash" + } + ], + "outputs": [], + "state_mutability": "external" + } + ] + }, + { + "type": "event", + "name": "dojo::components::upgradeable::upgradeable::Upgraded", + "kind": "struct", + "members": [ + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::components::upgradeable::upgradeable::Event", + "kind": "enum", + "variants": [ + { + "name": "Upgraded", + "type": "dojo::components::upgradeable::upgradeable::Upgraded", + "kind": "nested" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::something::something::Event", + "kind": "enum", + "variants": [ + { + "name": "UpgradeableEvent", + "type": "dojo::components::upgradeable::upgradeable::Event", + "kind": "nested" + } + ] + } + ], + "reads": [], + "writes": [], + "computed": [], + "init_calldata": [], + "tag": "dojo_examples-something", + "manifest_name": "dojo_examples-something-71cfad55" } ], "models": [ diff --git a/examples/spawn-and-move/manifests/dev/deployment/manifest.toml b/examples/spawn-and-move/manifests/dev/deployment/manifest.toml index 6c9080ead0..6b379c900d 100644 --- a/examples/spawn-and-move/manifests/dev/deployment/manifest.toml +++ b/examples/spawn-and-move/manifests/dev/deployment/manifest.toml @@ -1,10 +1,10 @@ [world] kind = "WorldContract" -class_hash = "0x210dd8e484e5555dc74a4a600b17878fc108911719b04139309acc874160c51" -original_class_hash = "0x210dd8e484e5555dc74a4a600b17878fc108911719b04139309acc874160c51" +class_hash = "0x2bcf11feac030c5ec81496dfc73ae256568c5b7518f8542e25dd0e42938de7e" +original_class_hash = "0x2bcf11feac030c5ec81496dfc73ae256568c5b7518f8542e25dd0e42938de7e" abi = "manifests/dev/deployment/abis/dojo-world.json" -address = "0x504b804eeac62e68d12dc030e56b8f62cb047950c346e60a974da02795f6aba" -transaction_hash = "0x65168705b42b38a0b9e290dfb079e023fa1960febb9fd7069fce5e369e3b56f" +address = "0x6d95c696211b4453e1f4b1b2dc9fb9d91602d4a7a1550567362bd9b8bcd9a82" +transaction_hash = "0x3290c6ba1226811dcf2c971b005dffd18965e93d0c11f9d8f2ae853d6890ab4" block_number = 3 seed = "dojo_examples" manifest_name = "dojo-world" @@ -23,9 +23,9 @@ manifest_name = "dojo-base" [[contracts]] kind = "DojoContract" -address = "0x2e85647f570d2a4abdffdd668823702548d20d1d6aaef74b6a4eb9670a32798" -class_hash = "0x647694c15fff8476c82ea146d0dbdbbb17d3425d5ba05a7320e4322f916df1d" -original_class_hash = "0x647694c15fff8476c82ea146d0dbdbbb17d3425d5ba05a7320e4322f916df1d" +address = "0x1a0504af4ffec1a748ae115e8d36b8cd7913298308ae4eb39e1eee8fc19d516" +class_hash = "0x288e853c84bde01bdbfbd8b8ffe0ff91ebbce90891e5d300f3395abbb50094d" +original_class_hash = "0x288e853c84bde01bdbfbd8b8ffe0ff91ebbce90891e5d300f3395abbb50094d" base_class_hash = "0x26a4f5d2d9638877a2648297339275df5eaab0adb3cdf0010887c2dbf2be4" abi = "manifests/dev/deployment/abis/contracts/dojo_examples-actions-40b6994c.json" reads = [] @@ -40,9 +40,9 @@ manifest_name = "dojo_examples-actions-40b6994c" [[contracts]] kind = "DojoContract" -address = "0x6a06eb156f956f1691bce4a4573c97b1a5f08d3bfa65fc25c4ed4b55d3e61a1" -class_hash = "0x97cd4fb3acfe9e6a024589ea34db2fc587586d699ef3732ce627e1771158ef" -original_class_hash = "0x97cd4fb3acfe9e6a024589ea34db2fc587586d699ef3732ce627e1771158ef" +address = "0x5a8f0aacc5fa9b30fdffee908d7e6093dedda92ad6deefff31aa06b473312e8" +class_hash = "0x761d18a3557d98b3962ebb2c9ddae89ad586ce81de7e86c5fd1e1b4f9d0028" +original_class_hash = "0x761d18a3557d98b3962ebb2c9ddae89ad586ce81de7e86c5fd1e1b4f9d0028" base_class_hash = "0x26a4f5d2d9638877a2648297339275df5eaab0adb3cdf0010887c2dbf2be4" abi = "manifests/dev/deployment/abis/contracts/dojo_examples-mock_token-31599eb2.json" reads = [] @@ -54,7 +54,7 @@ manifest_name = "dojo_examples-mock_token-31599eb2" [[contracts]] kind = "DojoContract" -address = "0x6359537114e0a62c63f52f2fb3c0e6241c9a2fcbd9dc9df221c867662aa31e9" +address = "0x5958b21ca9debb6bf444aebefef92305d3b0f3fd39e20097161282078666873" class_hash = "0x479bfb12dcba5398d77303e7a665fc3fedb16f2d7f9cb1f5d7e2beb3b7e2ba7" original_class_hash = "0x479bfb12dcba5398d77303e7a665fc3fedb16f2d7f9cb1f5d7e2beb3b7e2ba7" base_class_hash = "0x26a4f5d2d9638877a2648297339275df5eaab0adb3cdf0010887c2dbf2be4" @@ -70,6 +70,20 @@ init_calldata = [ tag = "dojo_examples-others" manifest_name = "dojo_examples-others-61de2c18" +[[contracts]] +kind = "DojoContract" +address = "0x20cf302cf7c93c871d2ec1bc0d4256e926a54b59ddbc3a6746f2b3430ab6f31" +class_hash = "0x2633dd37ecb3e273b309a3339da5dc820f2b77d4da474d7215952a1b60950dc" +original_class_hash = "0x2633dd37ecb3e273b309a3339da5dc820f2b77d4da474d7215952a1b60950dc" +base_class_hash = "0x26a4f5d2d9638877a2648297339275df5eaab0adb3cdf0010887c2dbf2be4" +abi = "manifests/dev/deployment/abis/contracts/dojo_examples-something-71cfad55.json" +reads = [] +writes = [] +computed = [] +init_calldata = [] +tag = "dojo_examples-something" +manifest_name = "dojo_examples-something-71cfad55" + [[models]] kind = "DojoModel" class_hash = "0x1da39caefeb15d61baa9d1d71f21ed79cf5650aa215b583e7f453c0d7d4ee65" diff --git a/examples/spawn-and-move/manifests/release/base/abis/contracts/dojo_examples-actions-40b6994c.json b/examples/spawn-and-move/manifests/release/base/abis/contracts/dojo_examples-actions-40b6994c.json index a8654af001..c2e9d96d5a 100644 --- a/examples/spawn-and-move/manifests/release/base/abis/contracts/dojo_examples-actions-40b6994c.json +++ b/examples/spawn-and-move/manifests/release/base/abis/contracts/dojo_examples-actions-40b6994c.json @@ -274,6 +274,30 @@ ], "state_mutability": "view" }, + { + "type": "function", + "name": "update_player_name", + "inputs": [ + { + "name": "name", + "type": "core::byte_array::ByteArray" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "update_player_name_value", + "inputs": [ + { + "name": "name", + "type": "core::byte_array::ByteArray" + } + ], + "outputs": [], + "state_mutability": "external" + }, { "type": "function", "name": "reset_player_config", diff --git a/examples/spawn-and-move/manifests/release/base/abis/dojo-world.json b/examples/spawn-and-move/manifests/release/base/abis/dojo-world.json index 0e5e96210e..6dd9a18e1a 100644 --- a/examples/spawn-and-move/manifests/release/base/abis/dojo-world.json +++ b/examples/spawn-and-move/manifests/release/base/abis/dojo-world.json @@ -46,6 +46,24 @@ } ] }, + { + "type": "enum", + "name": "dojo::world::ModelIndex", + "variants": [ + { + "name": "Keys", + "type": "core::array::Span::" + }, + { + "name": "Id", + "type": "core::felt252" + }, + { + "name": "MemberId", + "type": "(core::felt252, core::felt252)" + } + ] + }, { "type": "struct", "name": "core::array::Span::", @@ -282,12 +300,12 @@ "name": "entity", "inputs": [ { - "name": "model", + "name": "model_selector", "type": "core::felt252" }, { - "name": "keys", - "type": "core::array::Span::" + "name": "index", + "type": "dojo::world::ModelIndex" }, { "name": "layout", @@ -306,12 +324,12 @@ "name": "set_entity", "inputs": [ { - "name": "model", + "name": "model_selector", "type": "core::felt252" }, { - "name": "keys", - "type": "core::array::Span::" + "name": "index", + "type": "dojo::world::ModelIndex" }, { "name": "values", @@ -330,12 +348,12 @@ "name": "delete_entity", "inputs": [ { - "name": "model", + "name": "model_selector", "type": "core::felt252" }, { - "name": "keys", - "type": "core::array::Span::" + "name": "index", + "type": "dojo::world::ModelIndex" }, { "name": "layout", @@ -485,7 +503,7 @@ "name": "can_write_model", "inputs": [ { - "name": "model_id", + "name": "model_selector", "type": "core::felt252" }, { @@ -901,7 +919,7 @@ }, { "type": "event", - "name": "dojo::world::world::StoreDelRecord", + "name": "dojo::world::world::StoreUpdateRecord", "kind": "struct", "members": [ { @@ -910,12 +928,34 @@ "kind": "data" }, { - "name": "keys", + "name": "entity_id", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "values", "type": "core::array::Span::", "kind": "data" } ] }, + { + "type": "event", + "name": "dojo::world::world::StoreDelRecord", + "kind": "struct", + "members": [ + { + "name": "table", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "entity_id", + "type": "core::felt252", + "kind": "data" + } + ] + }, { "type": "event", "name": "dojo::world::world::WriterUpdated", @@ -1075,6 +1115,11 @@ "type": "dojo::world::world::StoreSetRecord", "kind": "nested" }, + { + "name": "StoreUpdateRecord", + "type": "dojo::world::world::StoreUpdateRecord", + "kind": "nested" + }, { "name": "StoreDelRecord", "type": "dojo::world::world::StoreDelRecord", diff --git a/examples/spawn-and-move/manifests/release/base/contracts/dojo_examples-actions-40b6994c.toml b/examples/spawn-and-move/manifests/release/base/contracts/dojo_examples-actions-40b6994c.toml index e5a46e3a69..175d7e1fd8 100644 --- a/examples/spawn-and-move/manifests/release/base/contracts/dojo_examples-actions-40b6994c.toml +++ b/examples/spawn-and-move/manifests/release/base/contracts/dojo_examples-actions-40b6994c.toml @@ -1,6 +1,6 @@ kind = "DojoContract" -class_hash = "0x1843e2e8c174c087de5ebaf04eee196eb0526b6345ad5ac3a6055d4e0dd1363" -original_class_hash = "0x1843e2e8c174c087de5ebaf04eee196eb0526b6345ad5ac3a6055d4e0dd1363" +class_hash = "0x288e853c84bde01bdbfbd8b8ffe0ff91ebbce90891e5d300f3395abbb50094d" +original_class_hash = "0x288e853c84bde01bdbfbd8b8ffe0ff91ebbce90891e5d300f3395abbb50094d" base_class_hash = "0x0" abi = "manifests/release/base/abis/contracts/dojo_examples-actions-40b6994c.json" reads = [] diff --git a/examples/spawn-and-move/manifests/release/base/contracts/dojo_examples-mock_token-31599eb2.toml b/examples/spawn-and-move/manifests/release/base/contracts/dojo_examples-mock_token-31599eb2.toml index 1ead2c6821..8e068df249 100644 --- a/examples/spawn-and-move/manifests/release/base/contracts/dojo_examples-mock_token-31599eb2.toml +++ b/examples/spawn-and-move/manifests/release/base/contracts/dojo_examples-mock_token-31599eb2.toml @@ -1,6 +1,6 @@ kind = "DojoContract" -class_hash = "0x97cd4fb3acfe9e6a024589ea34db2fc587586d699ef3732ce627e1771158ef" -original_class_hash = "0x97cd4fb3acfe9e6a024589ea34db2fc587586d699ef3732ce627e1771158ef" +class_hash = "0x761d18a3557d98b3962ebb2c9ddae89ad586ce81de7e86c5fd1e1b4f9d0028" +original_class_hash = "0x761d18a3557d98b3962ebb2c9ddae89ad586ce81de7e86c5fd1e1b4f9d0028" base_class_hash = "0x0" abi = "manifests/release/base/abis/contracts/dojo_examples-mock_token-31599eb2.json" reads = [] diff --git a/examples/spawn-and-move/manifests/release/base/dojo-world.toml b/examples/spawn-and-move/manifests/release/base/dojo-world.toml index 97f4f8c522..9ed318065b 100644 --- a/examples/spawn-and-move/manifests/release/base/dojo-world.toml +++ b/examples/spawn-and-move/manifests/release/base/dojo-world.toml @@ -1,6 +1,6 @@ kind = "Class" -class_hash = "0x210dd8e484e5555dc74a4a600b17878fc108911719b04139309acc874160c51" -original_class_hash = "0x210dd8e484e5555dc74a4a600b17878fc108911719b04139309acc874160c51" +class_hash = "0x2bcf11feac030c5ec81496dfc73ae256568c5b7518f8542e25dd0e42938de7e" +original_class_hash = "0x2bcf11feac030c5ec81496dfc73ae256568c5b7518f8542e25dd0e42938de7e" abi = "manifests/release/base/abis/dojo-world.json" tag = "dojo-world" manifest_name = "dojo-world" diff --git a/examples/spawn-and-move/src/actions.cairo b/examples/spawn-and-move/src/actions.cairo index 350ad568ee..7d04742378 100644 --- a/examples/spawn-and-move/src/actions.cairo +++ b/examples/spawn-and-move/src/actions.cairo @@ -8,6 +8,8 @@ trait IActions { fn move(ref world: IWorldDispatcher, direction: Direction); fn set_player_config(ref world: IWorldDispatcher, name: ByteArray); fn get_player_position(world: @IWorldDispatcher) -> Position; + fn update_player_name(ref world: IWorldDispatcher, name: ByteArray); + fn update_player_name_value(ref world: IWorldDispatcher, name: ByteArray); fn reset_player_config(ref world: IWorldDispatcher); fn set_player_server_profile(ref world: IWorldDispatcher, server_id: u32, name: ByteArray); #[cfg(feature: 'something')] @@ -27,7 +29,8 @@ mod actions { use starknet::{ContractAddress, get_caller_address}; use dojo_examples::models::{ - Position, Moves, Direction, Vec2, PlayerConfig, PlayerItem, ServerProfile + Position, Moves, Direction, Vec2, PlayerConfig, PlayerItem, ServerProfile, PositionTrait, + MovesTrait, MovesEntityTrait, PlayerConfigTrait, PlayerConfigEntityTrait }; use dojo_examples::utils::next_position; #[cfg(feature: 'something')] @@ -79,11 +82,28 @@ mod actions { fn move(ref world: IWorldDispatcher, direction: Direction) { let player = get_caller_address(); - let (mut position, mut moves) = get!(world, player, (Position, Moves)); + + // instead of using the `get!` macro, you can directly use + // the Trait::get method + let mut position = PositionTrait::get(world, player); + + // you can also get entity values by entity ID with the `EntityTrait` trait. + // Note that it returns a `Entity` struct which contains + // model values and the entity ID. + let move_id = MovesTrait::entity_id_from_keys(player); + let mut moves = MovesEntityTrait::get(world, move_id); + moves.remaining -= 1; moves.last_direction = direction; let next = next_position(position, direction); - set!(world, (moves, next)); + + // instead of using the `set!` macro, you can directly use + // the Trait::set method + next.set(world); + + // you can also update entity values by entity ID with the `EntityTrait` trait. + moves.update(world); + emit!(world, (Moved { player, direction })); } @@ -102,9 +122,11 @@ mod actions { fn reset_player_config(ref world: IWorldDispatcher) { let player = get_caller_address(); - let (position, moves, config) = get!(world, player, (Position, Moves, PlayerConfig)); + let (position, moves) = get!(world, player, (Position, Moves)); + let config = PlayerConfigTrait::get(world, player); - delete!(world, (position, moves, config)); + delete!(world, (position, moves)); + config.delete(world); let (position, moves, config) = get!(world, player, (Position, Moves, PlayerConfig)); @@ -136,6 +158,26 @@ mod actions { something.something(); } + + fn update_player_name(ref world: IWorldDispatcher, name: ByteArray) { + let player = get_caller_address(); + let config = PlayerConfigTrait::get(world, player); + config.set_name(world, name.clone()); + + let new_name = PlayerConfigTrait::get_name(world, player); + assert(new_name == name, 'unable to change name'); + } + + fn update_player_name_value(ref world: IWorldDispatcher, name: ByteArray) { + let player = get_caller_address(); + let config_id = PlayerConfigTrait::entity_id_from_keys(player); + + let config = PlayerConfigEntityTrait::get(world, config_id); + config.set_name(world, name.clone()); + + let new_name = PlayerConfigEntityTrait::get_name(world, config_id); + assert(new_name == name, 'unable to change name'); + } } // The `generate_trait` attribute is not compatible with `world` parameter expansion. @@ -188,6 +230,12 @@ mod tests { // System calls actions_system.spawn(); let initial_moves = get!(world, caller, Moves); + let initial_position = get!(world, caller, Position); + + assert( + initial_position.vec.x == 10 && initial_position.vec.y == 10, 'wrong initial position' + ); + actions_system.move(Direction::Right(())); let moves = get!(world, caller, Moves); @@ -197,7 +245,7 @@ mod tests { assert(moves.last_direction.into() == right_dir_felt, 'last direction is wrong'); let new_position = get!(world, caller, Position); - assert(new_position.vec.x == 11, 'position x is wrong'); - assert(new_position.vec.y == 10, 'position y is wrong'); + assert(new_position.vec.x == initial_position.vec.x + 1, 'position x is wrong'); + assert(new_position.vec.y == initial_position.vec.y, 'position y is wrong'); } } diff --git a/examples/spawn-and-move/src/mock_token.cairo b/examples/spawn-and-move/src/mock_token.cairo index 75b4c00e16..bd34916233 100644 --- a/examples/spawn-and-move/src/mock_token.cairo +++ b/examples/spawn-and-move/src/mock_token.cairo @@ -5,7 +5,6 @@ mod mock_token { fn dojo_init(world: @IWorldDispatcher) { let account: ContractAddress = get_caller_address(); - set!(world, MockToken { account: account, amount: 1000 }); } }