From c711e5663446c0d11d35ee230c067db028967223 Mon Sep 17 00:00:00 2001 From: WillQ Date: Sun, 11 Feb 2024 15:15:54 +0800 Subject: [PATCH] refactor: using components --- Scarb.lock | 4 +- Scarb.toml | 2 +- src/actions.cairo | 89 +++++++++++++++++ src/components/barn.cairo | 60 ++++++++++++ src/components/city_hall.cairo | 0 src/components/inner_city.cairo | 0 src/components/outer_city.cairo | 93 ++++++++++++++++++ src/components/warehouse.cairo | 76 +++++++++++++++ src/helpers/tuple.cairo | 120 +++++++++++++++++++++++ src/lib.cairo | 18 +++- src/models/barn.cairo | 25 ----- src/models/building.cairo | 49 ++++++++++ src/models/growth.cairo | 3 + src/models/level.cairo | 26 +++++ src/models/resource.cairo | 68 +++++++++++-- src/models/resource/brick.cairo | 40 -------- src/models/resource/cereal.cairo | 40 -------- src/models/resource/steel.cairo | 40 -------- src/models/resource/wood.cairo | 40 -------- src/models/resource_field.cairo | 55 ----------- src/models/warehouse.cairo | 40 -------- src/systems/actions.cairo | 160 ------------------------------- src/tests/test_world.cairo | 46 ++++----- src/tests/utils.cairo | 42 +++++--- 24 files changed, 637 insertions(+), 499 deletions(-) create mode 100644 src/actions.cairo create mode 100644 src/components/barn.cairo create mode 100644 src/components/city_hall.cairo create mode 100644 src/components/inner_city.cairo create mode 100644 src/components/outer_city.cairo create mode 100644 src/components/warehouse.cairo create mode 100644 src/helpers/tuple.cairo delete mode 100644 src/models/barn.cairo create mode 100644 src/models/building.cairo create mode 100644 src/models/growth.cairo create mode 100644 src/models/level.cairo delete mode 100644 src/models/resource/brick.cairo delete mode 100644 src/models/resource/cereal.cairo delete mode 100644 src/models/resource/steel.cairo delete mode 100644 src/models/resource/wood.cairo delete mode 100644 src/models/resource_field.cairo delete mode 100644 src/models/warehouse.cairo delete mode 100644 src/systems/actions.cairo diff --git a/Scarb.lock b/Scarb.lock index 67380f1..bc01496 100644 --- a/Scarb.lock +++ b/Scarb.lock @@ -3,8 +3,8 @@ version = 1 [[package]] name = "dojo" -version = "0.5.0" -source = "git+https://github.com/dojoengine/dojo#79278a62f66895cbe3bfaf822e3703309f8847b5" +version = "0.5.1" +source = "git+https://github.com/dojoengine/dojo#118ed84f7b5cb9e4e0c1963fca88b71a222ae50d" dependencies = [ "dojo_plugin", ] diff --git a/Scarb.toml b/Scarb.toml index 5ec5b82..f3e565c 100644 --- a/Scarb.toml +++ b/Scarb.toml @@ -7,7 +7,7 @@ version = "0.5.0" sierra-replace-ids = true [dependencies] -dojo = { git = "https://github.com/dojoengine/dojo", version = "0.5.0" } +dojo = { git = "https://github.com/dojoengine/dojo", version = "0.5.1" } openzeppelin = { git = "https://github.com/OpenZeppelin/cairo-contracts.git", tag = "v0.8.0" } [[target.dojo]] diff --git a/src/actions.cairo b/src/actions.cairo new file mode 100644 index 0000000..c1524a0 --- /dev/null +++ b/src/actions.cairo @@ -0,0 +1,89 @@ +use kingdom_lord::models::resource::{Wood, Brick, Steel, Cereal}; +use starknet::ContractAddress; + +const MAX_STORAGE: u64 = 100000; +const GROWTH_RATE: u64 = 10; + + +#[starknet::interface] +trait SpawnTrait{ + fn spawn(ref self: TState); +} + +// dojo decorator +#[dojo::contract] +mod kingdom_lord_controller { + use kingdom_lord::components::barn::{barn_component, Barn}; + use kingdom_lord::components::warehouse::{warehouse_component, Warehouse}; + use kingdom_lord::components::outer_city::{outer_city_component, OuterCity}; + use starknet::get_caller_address; + use core::starknet::info::get_block_number; + use super::{MAX_STORAGE, GROWTH_RATE, SpawnTrait}; + + + component!(path: barn_component, storage: barn, event: BarnEvent); + component!(path: warehouse_component, storage: warehouse, event: WarehouseEvent); + component!(path: outer_city_component, storage: outer_city, event: OuterCityEvent); + + #[storage] + struct Storage { + #[substorage(v0)] + barn: barn_component::Storage, + #[substorage(v0)] + warehouse: warehouse_component::Storage, + #[substorage(v0)] + outer_city: outer_city_component::Storage + } + + + #[event] + #[derive(Copy, Drop, starknet::Event)] + enum Event { + BarnEvent: barn_component::Event, + WarehouseEvent: warehouse_component::Event, + OuterCityEvent: outer_city_component::Event + } + + #[abi(embed_v0)] + impl KLBarnImpl = barn_component::BarnImpl; + + #[abi(embed_v0)] + impl KLWarehouseImpl = warehouse_component::WarehouseImpl; + + #[abi(embed_v0)] + impl KLOuterCityImpl = outer_city_component::OuterCityTraitImpl; + + + #[abi(embed_v0)] + impl GameSpawnImpl of SpawnTrait { + fn spawn(ref self: ContractState) { + let world = self.world_dispatcher.read(); + + let player = get_caller_address(); + + let block = get_block_number(); + + set!( + world, + ( + Warehouse { + player, + wood: 0_u64.into(), + steel: 0_u64.into(), + bricks: 0_u64.into(), + max_storage: MAX_STORAGE + }, + Barn { player, cereal: 0_u64.into(), max_storage: MAX_STORAGE }, + OuterCity { + player, + last_mined_block: block, + wood_field: Default::default(), + brick_field: Default::default(), + steel_field: Default::default(), + cereal_field: Default::default() + } + ) + ); + } + } +} diff --git a/src/components/barn.cairo b/src/components/barn.cairo new file mode 100644 index 0000000..4423b46 --- /dev/null +++ b/src/components/barn.cairo @@ -0,0 +1,60 @@ +use starknet::ContractAddress; +use super::super::models::resource::{Cereal, Resource}; + +#[derive(Model, Copy, Drop, Serde)] +struct Barn{ + #[key] + player: ContractAddress, + cereal: Resource, + max_storage: u64 +} + +trait BarnExtension{ + fn get_cereal(self: @Barn) -> Resource; + fn add_cereal(ref self: Barn, cereal: Resource); +} + +impl BarnTraitImpl of BarnExtension{ + fn get_cereal(self: @Barn) -> Resource{ + self.cereal.clone() + } + + fn add_cereal(ref self: Barn, cereal: Resource){ + self.cereal += cereal; + } +} + +#[starknet::interface] +trait BarnTrait{ + fn get_cereal(self: @TState) -> Resource; + fn add_cereal(self: @TState, cereal: Resource); +} + +#[starknet::component] +mod barn_component{ + use starknet::{get_contract_address}; + use core::starknet::info::get_block_number; + use dojo::world::{ + IWorldProvider, IWorldProviderDispatcher, IWorldDispatcher, IWorldDispatcherTrait + }; + use super::{Barn, Cereal, Resource, BarnExtension, BarnTrait}; + + #[storage] + struct Storage {} + + #[embeddable_as(BarnImpl)] + impl BarnTraitImpl< + TContractState, +HasComponent, +IWorldProvider + > of BarnTrait>{ + fn get_cereal(self: @ComponentState) -> Resource{ + let barn = get!(self.get_contract().world(), get_contract_address(), (Barn)); + barn.get_cereal() + } + fn add_cereal(self: @ComponentState, cereal: Resource){ + let world = self.get_contract().world(); + let mut barn = get!(world, get_contract_address(), (Barn)); + barn.add_cereal(cereal); + set!(world, (barn)) + } + } +} \ No newline at end of file diff --git a/src/components/city_hall.cairo b/src/components/city_hall.cairo new file mode 100644 index 0000000..e69de29 diff --git a/src/components/inner_city.cairo b/src/components/inner_city.cairo new file mode 100644 index 0000000..e69de29 diff --git a/src/components/outer_city.cairo b/src/components/outer_city.cairo new file mode 100644 index 0000000..adb8e2f --- /dev/null +++ b/src/components/outer_city.cairo @@ -0,0 +1,93 @@ +use starknet::ContractAddress; +use starknet::get_contract_address; +use super::super::models::building::{WoodBuilding, BrickBuilding, SteelBuilding, CerealBuilding}; +use super::super::models::resource::{Resource, Wood, Brick, Steel, Cereal}; +use super::super::models::level::{Level, GetLevel}; +use super::super::helpers::tuple::{TupleFour, TupleSix, TupleSize6Drop, TupleSize6Serde}; +use core::Serde; + + +type OuterCityLevelMap = ((Level, Level, Level, Level), (Level, Level, Level, Level), (Level, Level, Level, Level), (Level, Level, Level, Level, Level, Level)); + +#[derive(Model, Copy, Drop, Serde)] +struct OuterCity { + #[key] + player: ContractAddress, + last_mined_block: u64, + wood_field: TupleFour, + brick_field: TupleFour, + steel_field: TupleFour, + cereal_field: TupleSix, +} + +#[starknet::interface] +trait OuterCityTrait { + fn get_minable_resource(self: @TState)-> (Resource, Resource, Resource, Resource); + fn get_growth_rate(self: @TState) -> (u64, u64, u64, u64); + fn get_last_mined_block(self: @TState) -> u64; + fn get_outer_city_building_level(self: @TState) -> OuterCityLevelMap; +} + + + +#[starknet::component] +mod outer_city_component { + use starknet::{get_contract_address}; + use core::starknet::info::get_block_number; + use dojo::world::{ + IWorldProvider, IWorldProviderDispatcher, IWorldDispatcher, IWorldDispatcherTrait + }; + use super::{WoodBuilding, BrickBuilding, SteelBuilding, CerealBuilding}; + use super::{Resource, Wood, Brick, Steel, Cereal}; + use super::super::super::models::building::{Minable}; + use super::super::super::models::growth::Growth; + use super::{TupleSize6Serde, TupleSize6Drop}; + use super::{OuterCityTrait, OuterCity}; + use super::{OuterCityLevelMap, GetLevel}; + + #[storage] + struct Storage {} + + + #[embeddable_as(OuterCityTraitImpl)] + impl OuterCityImpl< + TContractState, +HasComponent, +IWorldProvider + > of OuterCityTrait> { + fn get_minable_resource(self: @ComponentState)-> (Resource, Resource, Resource, Resource){ + let outer_city = get!(self.get_contract().world(), get_contract_address(), (OuterCity)); + let current_block_number = get_block_number(); + let wood:u64 = outer_city.wood_field.get_minable(outer_city.last_mined_block, current_block_number); + let brick:u64 = outer_city.brick_field.get_minable(outer_city.last_mined_block, current_block_number); + let steel:u64 = outer_city.steel_field.get_minable(outer_city.last_mined_block, current_block_number); + let cereal:u64 = outer_city.cereal_field.get_minable(outer_city.last_mined_block, current_block_number); + ( + Resource::{amount: wood}, + Resource::{amount: brick}, + Resource::{amount: steel}, + Resource::{amount: cereal} + ) + } + + fn get_growth_rate(self: @ComponentState) -> (u64, u64, u64, u64){ + let outer_city = get!(self.get_contract().world(), get_contract_address(), (OuterCity)); + let wood_growth_rate = outer_city.wood_field.get_growth_rate(); + let brick_growth_rate = outer_city.brick_field.get_growth_rate(); + let steel_growth_rate = outer_city.steel_field.get_growth_rate(); + let cereal_growth_rate = outer_city.cereal_field.get_growth_rate(); + (wood_growth_rate, brick_growth_rate, steel_growth_rate, cereal_growth_rate) + } + + fn get_last_mined_block(self: @ComponentState) -> u64{ + get!(self.get_contract().world(), get_contract_address(), (OuterCity)).last_mined_block + } + + fn get_outer_city_building_level(self: @ComponentState) -> OuterCityLevelMap{ + let outer_city = get!(self.get_contract().world(), get_contract_address(), (OuterCity)); + let wood_level = outer_city.wood_field.get_level(); + let brick_level = outer_city.brick_field.get_level(); + let steel_level = outer_city.steel_field.get_level(); + let cereal_level = outer_city.cereal_field.get_level(); + (wood_level, brick_level, steel_level, cereal_level) + } + } +} diff --git a/src/components/warehouse.cairo b/src/components/warehouse.cairo new file mode 100644 index 0000000..36a9334 --- /dev/null +++ b/src/components/warehouse.cairo @@ -0,0 +1,76 @@ +use starknet::ContractAddress; +use super::super::models::resource::{Brick, Wood, Steel, Resource}; + +#[derive(Model, Copy, Drop, Serde)] +struct Warehouse { + #[key] + player: ContractAddress, + wood: Resource, + bricks: Resource, + steel: Resource, + max_storage: u64 +} + +trait WarehouseExtension { + fn get_resource(self:@Warehouse) -> (Resource, Resource, Resource); + fn add_resource(ref self:Warehouse, wood: Resource, bricks: Resource, steel: Resource); +} + +impl WarehouseExtensionImpl of WarehouseExtension{ + fn get_resource(self:@Warehouse) -> (Resource, Resource, Resource) { + (self.wood.clone(), self.bricks.clone(), self.steel.clone()) + } + + fn add_resource(ref self:Warehouse, wood: Resource, bricks: Resource, steel: Resource) { + self.wood += wood; + self.bricks += bricks; + self.steel += steel; + } +} + +trait AdminWareHouseTrait { + fn set_max_storage(ref self: Warehouse, max_storage: u64); +} + +impl AdminWareHouseImpl of AdminWareHouseTrait{ + fn set_max_storage(ref self: Warehouse, max_storage: u64) { + self.max_storage = max_storage; + } +} + +#[starknet::interface] +trait WarehouseTrait { + fn get_resource(self:@TState) -> (Resource, Resource, Resource); + fn add_resource(self:@TState, wood: Resource, bricks: Resource, steel: Resource); +} + + +#[starknet::component] +mod warehouse_component{ + use starknet::{get_contract_address}; + use core::starknet::info::get_block_number; + use dojo::world::{ + IWorldProvider, IWorldProviderDispatcher, IWorldDispatcher, IWorldDispatcherTrait + }; + use super::{Warehouse, WarehouseTrait, Brick, Wood, Steel, Resource, WarehouseExtension}; + + #[storage] + struct Storage {} + + #[embeddable_as(WarehouseImpl)] + impl WarehouseTraitImpl< + TContractState, +HasComponent, +IWorldProvider + > of WarehouseTrait>{ + fn get_resource(self:@ComponentState) -> (Resource, Resource, Resource){ + let warehouse = get!(self.get_contract().world(), get_contract_address(), (Warehouse)); + warehouse.get_resource() + } + fn add_resource(self:@ComponentState, wood: Resource, bricks: Resource, steel: Resource){ + let world = self.get_contract().world(); + let mut warehouse: Warehouse = get!(world, get_contract_address(), (Warehouse)); + warehouse.add_resource(wood, bricks, steel); + set!(world, (warehouse)) + } + } +} + diff --git a/src/helpers/tuple.cairo b/src/helpers/tuple.cairo new file mode 100644 index 0000000..b2055f0 --- /dev/null +++ b/src/helpers/tuple.cairo @@ -0,0 +1,120 @@ +use core::serde::Serde; +use super::super::models::building::{Minable, Building}; +use super::super::models::growth::Growth; +use super::super::models::level::{GetLevel, Level}; +#[derive(Serde, Drop, Copy, Introspect, Default)] +struct TupleFour { + first: T, + second: T, + third: T, + forth: T +} + +impl MinableFourImpl> of Minable> { + fn get_minable(self: @TupleFour, last_block_number: u64, current_block_number: u64) -> u64 { + self.first.get_minable(last_block_number, current_block_number) + + self.second.get_minable(last_block_number, current_block_number) + + self.third.get_minable(last_block_number, current_block_number) + + self.forth.get_minable(last_block_number, current_block_number) + } +} + +impl GrowthFourImpl> of Growth> { + fn get_growth_rate(self: @TupleFour) -> u64 { + self.first.get_growth_rate() + + self.second.get_growth_rate() + + self.third.get_growth_rate() + + self.forth.get_growth_rate() + } +} + +impl GetLevelFourImpl> of GetLevel, (Level, Level, Level, Level)> { + fn get_level(self: @TupleFour) -> (Level, Level, Level, Level) { + (self.first.get_level(), self.second.get_level(), self.third.get_level(), self.forth.get_level()) + } +} + +#[derive(Serde, Drop, Copy, Introspect, Default)] +struct TupleSix { + first: T, + second: T, + third: T, + forth: T, + fifth: T, + sixth: T +} + +impl MinableSixImpl> of Minable> { + fn get_minable(self: @TupleSix, last_block_number: u64, current_block_number: u64) -> u64 { + self.first.get_minable(last_block_number, current_block_number) + + self.second.get_minable(last_block_number, current_block_number) + + self.third.get_minable(last_block_number, current_block_number) + + self.forth.get_minable(last_block_number, current_block_number) + + self.fifth.get_minable(last_block_number, current_block_number) + + self.sixth.get_minable(last_block_number, current_block_number) + } +} + +impl GrowthSixImpl> of Growth> { + fn get_growth_rate(self: @TupleSix) -> u64 { + self.first.get_growth_rate() + + self.second.get_growth_rate() + + self.third.get_growth_rate() + + self.forth.get_growth_rate() + + self.fifth.get_growth_rate() + + self.sixth.get_growth_rate() + } +} + +impl GetLevelSixImpl> of GetLevel, (Level, Level, Level, Level, Level, Level)> { + fn get_level(self: @TupleSix) -> (Level, Level, Level, Level, Level, Level) { + (self.first.get_level(), self.second.get_level(), self.third.get_level(), self.forth.get_level(), self.fifth.get_level(), self.sixth.get_level()) + } +} + +impl TupleSize6Serde< + E0, + E1, + E2, + E3, + E4, + E5, + +Serde, + +Drop, + +Serde, + +Drop, + +Serde, + +Drop, + +Serde, + +Drop, + +Serde, + +Drop, + +Serde, + +Drop +> of Serde<(E0, E1, E2, E3, E4, E5)> { + fn serialize(self: @(E0, E1, E2, E3, E4, E5), ref output: Array) { + let (e0, e1, e2, e3, e4, e5) = self; + e0.serialize(ref output); + e1.serialize(ref output); + e2.serialize(ref output); + e3.serialize(ref output); + e4.serialize(ref output); + e5.serialize(ref output); + } + fn deserialize(ref serialized: Span) -> Option<(E0, E1, E2, E3, E4, E5)> { + Option::Some( + ( + Serde::deserialize(ref serialized)?, + Serde::deserialize(ref serialized)?, + Serde::deserialize(ref serialized)?, + Serde::deserialize(ref serialized)?, + Serde::deserialize(ref serialized)?, + Serde::deserialize(ref serialized)? + ) + ) + } +} + +impl TupleSize6Drop< + E0, E1, E2, E3,E4, E5, +Drop, +Drop, +Drop, +Drop, +Drop, +Drop +> of Drop<(E0, E1, E2, E3, E4, E5)>; diff --git a/src/lib.cairo b/src/lib.cairo index fc270e1..d373c0c 100644 --- a/src/lib.cairo +++ b/src/lib.cairo @@ -1,15 +1,23 @@ -mod systems { - mod actions; -} +mod actions; mod models { mod resource; - mod resource_field; + mod building; + mod level; + mod growth; +} + +mod components { + mod outer_city; mod warehouse; mod barn; } +mod helpers { + mod tuple; +} + mod tests { mod test_world; mod utils; -} +} \ No newline at end of file diff --git a/src/models/barn.cairo b/src/models/barn.cairo deleted file mode 100644 index bb334b1..0000000 --- a/src/models/barn.cairo +++ /dev/null @@ -1,25 +0,0 @@ -use starknet::ContractAddress; -use super::resource::Cereal; - -#[derive(Model, Drop, Serde)] -struct Barn{ - #[key] - player: ContractAddress, - cereal: Cereal, - max_storage: u64 -} - -trait BarnTrait{ - fn get_cereal(self: @Barn) -> Cereal; - fn add_cereal(ref self: Barn, cereal: Cereal); -} - -impl BarnTraitImpl of BarnTrait{ - fn get_cereal(self: @Barn) -> Cereal{ - self.cereal.clone() - } - - fn add_cereal(ref self: Barn, cereal: Cereal){ - self.cereal += cereal; - } -} \ No newline at end of file diff --git a/src/models/building.cairo b/src/models/building.cairo new file mode 100644 index 0000000..35b848b --- /dev/null +++ b/src/models/building.cairo @@ -0,0 +1,49 @@ +use core::clone::Clone; +use super::level::{Level, GetLevel}; +use super::resource::{Resource, Wood, Brick, Steel, Cereal}; +use super::growth::Growth; + +#[derive(Drop, Introspect, Copy, Serde, Default)] +struct Building{ + growth_rate: u64, + level: Level, + item: T +} + +impl GetLevelImpl of GetLevel, Level>{ + fn get_level(self: @Building) -> Level{ + self.level.clone() + } +} + +impl GrowthRate of Growth>{ + fn get_growth_rate(self: @Building) -> u64{ + *self.growth_rate * *self.level.level + } + +} + +trait Minable{ + fn get_minable(self: @T, last_block_number:u64, current_block_number: u64) -> u64; +} + +impl MinableImpl> of Minable>{ + fn get_minable(self: @Building, last_block_number:u64, current_block_number: u64)-> u64{ + self.get_growth_rate() * (current_block_number - last_block_number) + } +} + + + +#[derive(Drop, Introspect, Copy, Serde)] +struct BuildingUpResource{ + wood: Resource, + brick: Resource, + steel: Resource, + cereal: Resource, +} + +type WoodBuilding = Building; +type SteelBuilding = Building; +type BrickBuilding = Building; +type CerealBuilding = Building; \ No newline at end of file diff --git a/src/models/growth.cairo b/src/models/growth.cairo new file mode 100644 index 0000000..20def46 --- /dev/null +++ b/src/models/growth.cairo @@ -0,0 +1,3 @@ +trait Growth{ + fn get_growth_rate(self: @T) -> u64; +} \ No newline at end of file diff --git a/src/models/level.cairo b/src/models/level.cairo new file mode 100644 index 0000000..077a143 --- /dev/null +++ b/src/models/level.cairo @@ -0,0 +1,26 @@ +#[derive(Drop, Serde, Introspect, Copy, Default)] +struct Level{ + level: u64, +} + +trait LevelTrait{ + fn level_up(self: Level) -> Level; +} + +trait GetLevel{ + fn get_level(self: @T) -> R; +} + + +impl LevelImpl of LevelTrait{ + fn level_up(self: Level) -> Level{ + Level{level: self.level + 1} + } +} + +impl GetLevelImpl of GetLevel{ + fn get_level(self: @Level) -> Level{ + Level {level: *self.level} + } +} + diff --git a/src/models/resource.cairo b/src/models/resource.cairo index 7e78775..0dfcae7 100644 --- a/src/models/resource.cairo +++ b/src/models/resource.cairo @@ -1,12 +1,62 @@ -mod brick; -mod cereal; -mod steel; -mod wood; - -use steel::Steel; -use wood::Wood; -use cereal::Cereal; -use brick::Brick; +#[derive(Drop, Introspect, Copy, Serde)] +struct Resource{ + amount: u64 +} + +impl ResourceAdd of Add>{ + fn add(lhs: Resource, rhs: Resource) -> Resource { + Resource { amount: lhs.amount + rhs.amount } + } +} + +impl ResourceAddEq of AddEq>{ + fn add_eq(ref self: Resource, other: Resource) { + self.amount += other.amount; + } +} + +impl ResourceSub of Sub>{ + fn sub(lhs: Resource, rhs: Resource) -> Resource { + Resource { amount: lhs.amount - rhs.amount } + } +} + +impl ResourceSubEq of SubEq>{ + fn sub_eq(ref self: Resource, other: Resource) { + self.amount -= other.amount; + } +} + +impl ResourceFrom of Into>{ + fn into(self: u64) -> Resource { + Resource{ amount: self} + } +} + +impl ResourceInto of Into, u64>{ + fn into(self: Resource) -> u64 { + self.amount + } +} + +impl ResourcePartialEq of PartialEq>{ + fn eq(lhs: @Resource, rhs: @Resource) -> bool{ + lhs.amount == rhs.amount + } + fn ne(lhs: @Resource, rhs: @Resource) -> bool{ + !(lhs.amount == rhs.amount) + } +} + + +#[derive(Drop, Introspect, Copy, Serde, Default)] +struct Steel{} +#[derive(Drop, Introspect, Copy, Serde, Default)] +struct Wood{} +#[derive(Drop, Introspect, Copy, Serde, Default)] +struct Cereal{} +#[derive(Drop, Introspect, Copy, Serde, Default)] +struct Brick{} trait Minable { fn mine(growth_rate: u64, last_block_number:u64, current_block_number: u64) -> T; diff --git a/src/models/resource/brick.cairo b/src/models/resource/brick.cairo deleted file mode 100644 index c603456..0000000 --- a/src/models/resource/brick.cairo +++ /dev/null @@ -1,40 +0,0 @@ -#[derive(Drop, Serde, Copy, Introspect, PartialEq)] -struct Brick { - amount: u64, -} - -impl BrickAdd of Add{ - fn add(lhs: Brick, rhs: Brick) -> Brick { - Brick { amount: lhs.amount + rhs.amount } - } -} - -impl BrickAddEq of AddEq{ - fn add_eq(ref self: Brick, other: Brick) { - self.amount += other.amount; - } -} - -impl BrickSub of Sub{ - fn sub(lhs: Brick, rhs: Brick) -> Brick { - Brick { amount: lhs.amount - rhs.amount } - } -} - -impl BrickSubEq of SubEq{ - fn sub_eq(ref self: Brick, other: Brick) { - self.amount -= other.amount; - } -} - -impl BrickFrom of Into{ - fn into(self: u64) -> Brick { - Brick{ amount: self} - } -} - -impl BrickInto of Into{ - fn into(self: Brick) -> u64 { - self.amount - } -} diff --git a/src/models/resource/cereal.cairo b/src/models/resource/cereal.cairo deleted file mode 100644 index f5a6e4a..0000000 --- a/src/models/resource/cereal.cairo +++ /dev/null @@ -1,40 +0,0 @@ -#[derive(Drop, Serde, Copy, Introspect, PartialEq)] -struct Cereal { - amount: u64, -} - -impl CerealAdd of Add{ - fn add(lhs: Cereal, rhs: Cereal) -> Cereal { - Cereal { amount: lhs.amount + rhs.amount } - } -} - -impl CerealAddEq of AddEq{ - fn add_eq(ref self: Cereal, other: Cereal) { - self.amount += other.amount; - } -} - -impl CerealSub of Sub{ - fn sub(lhs: Cereal, rhs: Cereal) -> Cereal { - Cereal { amount: lhs.amount - rhs.amount } - } -} - -impl CerealSubEq of SubEq{ - fn sub_eq(ref self: Cereal, other: Cereal) { - self.amount -= other.amount; - } -} - -impl CerealFrom of Into{ - fn into(self: u64) -> Cereal { - Cereal{ amount: self} - } -} - -impl CerealInto of Into{ - fn into(self: Cereal) -> u64 { - self.amount - } -} diff --git a/src/models/resource/steel.cairo b/src/models/resource/steel.cairo deleted file mode 100644 index 8d24216..0000000 --- a/src/models/resource/steel.cairo +++ /dev/null @@ -1,40 +0,0 @@ -#[derive(Drop, Serde, Copy, Introspect, PartialEq)] -struct Steel { - amount: u64, -} - -impl SteelAdd of Add{ - fn add(lhs: Steel, rhs: Steel) -> Steel { - Steel { amount: lhs.amount + rhs.amount } - } -} - -impl SteelAddEq of AddEq{ - fn add_eq(ref self: Steel, other: Steel) { - self.amount += other.amount; - } -} - -impl SteelSub of Sub{ - fn sub(lhs: Steel, rhs: Steel) -> Steel { - Steel { amount: lhs.amount - rhs.amount } - } -} - -impl SteelSubEq of SubEq{ - fn sub_eq(ref self: Steel, other: Steel) { - self.amount -= other.amount; - } -} - -impl SteelFrom of Into{ - fn into(self: u64) -> Steel { - Steel{ amount: self} - } -} - -impl SteelInto of Into{ - fn into(self: Steel) -> u64 { - self.amount - } -} diff --git a/src/models/resource/wood.cairo b/src/models/resource/wood.cairo deleted file mode 100644 index e960f9c..0000000 --- a/src/models/resource/wood.cairo +++ /dev/null @@ -1,40 +0,0 @@ -#[derive(Drop, Serde, Copy, Introspect, PartialEq)] -struct Wood { - amount: u64, -} - -impl WoodAdd of Add{ - fn add(lhs: Wood, rhs: Wood) -> Wood { - Wood { amount: lhs.amount + rhs.amount } - } -} - -impl WoodAddEq of AddEq{ - fn add_eq(ref self: Wood, other: Wood) { - self.amount += other.amount; - } -} - -impl WoodSub of Sub{ - fn sub(lhs: Wood, rhs: Wood) -> Wood { - Wood { amount: lhs.amount - rhs.amount } - } -} - -impl WoodSubEq of SubEq{ - fn sub_eq(ref self: Wood, other: Wood) { - self.amount -= other.amount; - } -} - -impl WoodFrom of Into{ - fn into(self: u64) -> Wood { - Wood{ amount: self} - } -} - -impl WoodInto of Into{ - fn into(self: Wood) -> u64 { - self.amount - } -} diff --git a/src/models/resource_field.cairo b/src/models/resource_field.cairo deleted file mode 100644 index 49d3037..0000000 --- a/src/models/resource_field.cairo +++ /dev/null @@ -1,55 +0,0 @@ -use starknet::ContractAddress; -use super::resource::{Wood, Brick, Steel, Cereal, MinableImpl}; - -#[derive(Model, Drop, Serde)] -struct ResourceField { - #[key] - player: ContractAddress, - last_mined_block: u64, - growth_rate: u64, -} - -trait ResourceFieldTrait{ - fn mine(ref self: ResourceField, block_number: u64) -> (Wood, Brick, Steel, Cereal); - fn get_minable(self: @ResourceField, block_number: u64) -> (Wood, Brick, Steel, Cereal); - fn get_growth_rate(self: @ResourceField) -> u64; - fn get_last_mined_block(self: @ResourceField) -> u64; -} - -impl ResourceFieldTraitImpl of ResourceFieldTrait{ - fn mine(ref self: ResourceField, block_number: u64) -> (Wood, Brick, Steel, Cereal){ - let (wood, bricks, steel, cereals) = self.get_minable(block_number); - self.last_mined_block = block_number; - (wood, bricks, steel, cereals) - } - - fn get_minable(self: @ResourceField, block_number: u64) -> (Wood, Brick, Steel, Cereal){ - let growth_rate = self.get_growth_rate(); - let wood: Wood = MinableImpl::mine(growth_rate, self.last_mined_block.clone(), block_number); - let steel: Steel = MinableImpl::mine(growth_rate, self.last_mined_block.clone(), block_number); - let bricks: Brick = MinableImpl::mine(growth_rate, self.last_mined_block.clone(), block_number); - let cereals: Cereal = MinableImpl::mine(growth_rate, self.last_mined_block.clone(), block_number); - (wood, bricks, steel, cereals) - } - - fn get_growth_rate(self: @ResourceField) -> u64{ - self.growth_rate.clone() - } - - fn get_last_mined_block(self: @ResourceField) -> u64{ - self.last_mined_block.clone() - } -} - - -trait AdminResourceFieldTrait{ - fn set_growth_rate(ref self: ResourceField, growth_rate: u64); -} - -impl AdminResourceFieldTraitImpl of AdminResourceFieldTrait{ - - fn set_growth_rate(ref self: ResourceField, growth_rate: u64){ - self.growth_rate = growth_rate; - } -} - diff --git a/src/models/warehouse.cairo b/src/models/warehouse.cairo deleted file mode 100644 index dc1bba6..0000000 --- a/src/models/warehouse.cairo +++ /dev/null @@ -1,40 +0,0 @@ -use starknet::ContractAddress; -use super::resource::{Brick, Wood, Steel}; - -#[derive(Model, Drop, Serde)] -struct Warehouse { - #[key] - player: ContractAddress, - wood: Wood, - bricks: Brick, - steel: Steel, - max_storage: u64 -} - -trait WarehouseTrait { - fn get_resource(self:@Warehouse) -> (@Wood, @Brick, @Steel); - fn add_resource(ref self:Warehouse, wood: Wood, bricks: Brick, steel: Steel); -} - -impl WarehouseTraitImpl of WarehouseTrait{ - fn get_resource(self:@Warehouse) -> (@Wood, @Brick, @Steel) { - (self.wood, self.bricks, self.steel) - } - - fn add_resource(ref self:Warehouse, wood: Wood, bricks: Brick, steel: Steel) { - self.wood += wood; - self.bricks += bricks; - self.steel += steel; - } -} - -trait AdminWareHouseTrait { - fn set_max_storage(ref self: Warehouse, max_storage: u64); -} - -impl AdminWareHouseImpl of AdminWareHouseTrait{ - fn set_max_storage(ref self: Warehouse, max_storage: u64) { - self.max_storage = max_storage; - } -} - diff --git a/src/systems/actions.cairo b/src/systems/actions.cairo deleted file mode 100644 index 14d8acb..0000000 --- a/src/systems/actions.cairo +++ /dev/null @@ -1,160 +0,0 @@ -use kingdom_lord::models::resource::{Wood, Brick, Steel, Cereal}; -use starknet::ContractAddress; - -const MAX_STORAGE: u64 = 100000; -const GROWTH_RATE: u64 = 10; - - -// dojo decorator -#[dojo::contract] -mod actions { - use super::{MAX_STORAGE, GROWTH_RATE}; - use starknet::{ContractAddress, get_caller_address, get_block_timestamp}; - use kingdom_lord::models::barn::{Barn, BarnTrait}; - use kingdom_lord::models::warehouse::{Warehouse, WarehouseTrait, AdminWareHouseTrait}; - use kingdom_lord::models::resource_field::{ResourceField, ResourceFieldTrait, AdminResourceFieldTrait}; - use kingdom_lord::models::resource::{Wood, Brick, Steel, Cereal}; - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - NewUserCreatedEvent: NewUserCreatedEvent, - MineResourceEvent: MineResourceEvent, - SetMinableResourceEvent: SetMinableResourceEvent, - SetGrowthRateEvent: SetGrowthRateEvent, - } - - #[derive(Drop, starknet::Event)] - struct NewUserCreatedEvent { - player: ContractAddress, - } - - #[derive(Drop, starknet::Event)] - struct MineResourceEvent { - player: ContractAddress, - wood: u64, - steel: u64, - cereals: u64, - bricks: u64 - } - - #[derive(Drop, starknet::Event)] - struct SetMinableResourceEvent { - player: ContractAddress, - origin_value: u64, - new_value: u64 - } - - #[derive(Drop, starknet::Event)] - struct SetGrowthRateEvent { - player: ContractAddress, - origin_value: u64, - new_value: u64 - } - - #[starknet::interface] - trait ResourceActions { - fn spawn(self: @TContractState); - fn mine(self: @TContractState); - fn get_minable_resource(self: @TContractState)-> (Wood, Brick, Steel, Cereal); - fn get_growth_rate(self: @TContractState) -> u64; - } - - #[starknet::interface] - trait AdminActions { - fn set_minable_growth_rate(ref self: TContractState, player: ContractAddress, growth_rate: u64); - fn set_warehouse_size(ref self: TContractState, player: ContractAddress, size: u64); - } - - // impl: implement functions specified in trait - #[abi(embed_v0)] - impl ResourceActionImpl of ResourceActions { - // ContractState is defined by system decorator expansion - fn spawn(self: @ContractState) { - // Access the world dispatcher for reading. - let world = self.world_dispatcher.read(); - - let player = get_caller_address(); - - let warehouse = get!(world, player, (Warehouse)); - - let barn = get!(world, player, (Barn)); - - let resource_field = get!(world, player, (ResourceField)); - let block = get_block_timestamp(); - - set!( - world, - ( - Warehouse { - player, - wood: 0_u64.into(), - steel: 0_u64.into(), - bricks: 0_u64.into(), - max_storage: MAX_STORAGE - }, - Barn { player, cereal: 0_u64.into(), max_storage: MAX_STORAGE }, - ResourceField { player, last_mined_block: block, growth_rate: GROWTH_RATE } - ) - ); - emit!(world, NewUserCreatedEvent{player}); - } - - fn mine(self: @ContractState) { - let world = self.world_dispatcher.read(); - - let player = get_caller_address(); - - let mut warehouse = get!(world, player, (Warehouse)); - - let mut barn = get!(world, player, (Barn)); - - let mut resource_field = get!(world, player, (ResourceField)); - - let block = get_block_timestamp(); - - let (wood, brick, steel, cereal) = resource_field.mine(block); - - warehouse.add_resource(wood, brick, steel); - barn.add_cereal(cereal); - set!(world, (warehouse)); - set!(world, (barn)); - emit!(world, MineResourceEvent{player, wood: wood.into(), steel: steel.into(), cereals: cereal.into(), bricks: brick.into()}); - } - - fn get_minable_resource(self: @ContractState) -> (Wood, Brick, Steel, Cereal){ - let world = self.world_dispatcher.read(); - let player = get_caller_address(); - let block = get_block_timestamp(); - let resource_field = get!(world, player, (ResourceField)); - let (wood, brick, steel, cereal) = resource_field.get_minable(block); - (wood.clone(), brick.clone(), steel.clone(), cereal.clone()) - } - - fn get_growth_rate(self: @ContractState) -> u64 { - let world = self.world_dispatcher.read(); - let player = get_caller_address(); - let resource_field = get!(world, player, (ResourceField)); - resource_field.get_growth_rate() - } - } - - - #[abi(embed_v0)] - impl AdminActionsImpl of AdminActions { - fn set_minable_growth_rate(ref self: ContractState, player: ContractAddress, growth_rate: u64){ - let world = self.world_dispatcher.read(); - let player = get_caller_address(); - let mut resource_field = get!(world, player, (ResourceField)); - resource_field.set_growth_rate(growth_rate); - set!(world, (resource_field)); - } - fn set_warehouse_size(ref self: ContractState, player: ContractAddress, size: u64){ - let world = self.world_dispatcher.read(); - let player = get_caller_address(); - let mut warehouse = get!(world, player, (Warehouse)); - warehouse.set_max_storage(size); - set!(world, (warehouse)); - } - } -} diff --git a/src/tests/test_world.cairo b/src/tests/test_world.cairo index 6a6af6d..76d4704 100644 --- a/src/tests/test_world.cairo +++ b/src/tests/test_world.cairo @@ -1,7 +1,7 @@ #[cfg(test)] mod tests { - use kingdom_lord::systems::actions::actions::AdminActionsDispatcherTrait; - use starknet::class_hash::Felt252TryIntoClassHash; + use kingdom_lord::actions::SpawnTraitDispatcherTrait; +use starknet::class_hash::Felt252TryIntoClassHash; use starknet::get_caller_address; // import world dispatcher @@ -9,48 +9,34 @@ mod tests { // import test utils use dojo::test_utils::{spawn_test_world, deploy_contract}; - use kingdom_lord::tests::utils::setup_world; - use kingdom_lord::models::{ - resource_field::{ResourceField, resource_field}, warehouse::{Warehouse, warehouse}, - barn::{Barn, barn} - }; + use kingdom_lord::actions::{SpawnTraitDispatcher}; + use kingdom_lord::components::barn::BarnTraitDispatcherTrait; + use kingdom_lord::components::outer_city::OuterCityTraitDispatcherTrait; + use kingdom_lord::components::warehouse::WarehouseTraitDispatcherTrait; - use kingdom_lord::systems::actions::{actions, actions::{ResourceActionsDispatcher, ResourceActionsDispatcherTrait, AdminActionsDispatcher, AdminActions}}; #[test] - #[available_gas(30000000)] + #[available_gas(300000000000)] fn test_mine() { - // caller - let caller = starknet::contract_address_const::<0x0>(); - - // models - let mut models = array![resource_field::TEST_CLASS_HASH, warehouse::TEST_CLASS_HASH, barn::TEST_CLASS_HASH]; // deploy world with models - let world = spawn_test_world(models); + let context = setup_world(); - // deploy systems contract - let contract_address = world - .deploy_contract('salt', actions::TEST_CLASS_HASH.try_into().unwrap()); - let actions_system = ResourceActionsDispatcher { contract_address }; - let admin_system = AdminActionsDispatcher{ contract_address }; + context.spawn_trait.spawn(); + let (wood,brick,steel,cereal) = context.outer_city_trait.get_minable_resource(); - // call spawn() - actions_system.spawn(); - - let (wood,brick,steel,cereal) = actions_system.get_minable_resource(); assert(wood == 0_u64.into(), 'wood'); assert(brick == 0_u64.into(), 'brick'); assert(steel == 0_u64.into(), 'steel'); assert(cereal == 0_u64.into(), 'cereal'); - let player = get_caller_address(); - let growth_rate = actions_system.get_growth_rate(); - assert(growth_rate == 10_u64, 'growth rate should be 10'); - admin_system.set_minable_growth_rate(player, 100); - let growth_rate = actions_system.get_growth_rate(); - assert(growth_rate == 100_u64, 'growth rate should be 100'); + let (wood_growth_rate, steel_growth_rate, brick_growth_rate, cereal_growth_rate) = context.outer_city_trait.get_growth_rate(); + assert(wood_growth_rate == 0_u64, 'wood growth rate should be 0'); + assert(steel_growth_rate == 0_u64, 'wood growth rate should be 0'); + assert(brick_growth_rate == 0_u64, 'wood growth rate should be 0'); + assert(cereal_growth_rate == 0_u64, 'wood growth rate should be 0'); + } } diff --git a/src/tests/utils.cairo b/src/tests/utils.cairo index 53b8117..8f51bda 100644 --- a/src/tests/utils.cairo +++ b/src/tests/utils.cairo @@ -1,18 +1,31 @@ #[cfg(test)] use dojo::test_utils::{spawn_test_world, deploy_contract}; -// use kingdom_lord::models::resource::{, Brick, Cereal, Wood}; -use kingdom_lord::models::barn::barn; -use kingdom_lord::models::resource_field::resource_field; -use kingdom_lord::models::warehouse::warehouse; +use kingdom_lord::components::barn::barn; +use starknet::ContractAddress; +use kingdom_lord::components::outer_city::outer_city; +use kingdom_lord::components::warehouse::warehouse; use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait}; -use kingdom_lord::systems::actions::actions; -use kingdom_lord::systems::actions::actions::{ResourceActions, ResourceActionsDispatcher, ResourceActionsDispatcherTrait}; +use kingdom_lord::actions::{kingdom_lord_controller, SpawnTraitDispatcher}; +use kingdom_lord::actions::kingdom_lord_controller::world_dispatcherContractMemberStateTrait; +use kingdom_lord::components::barn::BarnTraitDispatcher; +use kingdom_lord::components::warehouse::WarehouseTraitDispatcher; +use kingdom_lord::components::outer_city::OuterCityTraitDispatcher; + +#[derive(Drop, Clone)] +struct TextContext{ + world: IWorldDispatcher, + contract_address: ContractAddress, + spawn_trait: SpawnTraitDispatcher, + barn_trait: BarnTraitDispatcher, + warehouse_trait: WarehouseTraitDispatcher, + outer_city_trait: OuterCityTraitDispatcher, +} #[cfg(test)] -fn setup_world() -> (IWorldDispatcher, ResourceActionsDispatcher) { +fn setup_world() -> TextContext { let mut models = array![ barn::TEST_CLASS_HASH, - resource_field::TEST_CLASS_HASH, + outer_city::TEST_CLASS_HASH, warehouse::TEST_CLASS_HASH, ]; // deploy world with models @@ -20,8 +33,13 @@ fn setup_world() -> (IWorldDispatcher, ResourceActionsDispatcher) { // deploy systems contract let contract_address = world - .deploy_contract('salt', actions::TEST_CLASS_HASH.try_into().unwrap()); - let actions_system = ResourceActionsDispatcher { contract_address }; - - (world, actions_system) + .deploy_contract('salt', kingdom_lord_controller::TEST_CLASS_HASH.try_into().unwrap()); + TextContext{ + world, + contract_address, + spawn_trait: SpawnTraitDispatcher{ contract_address }, + barn_trait: BarnTraitDispatcher{ contract_address }, + warehouse_trait: WarehouseTraitDispatcher{ contract_address}, + outer_city_trait: OuterCityTraitDispatcher{ contract_address }, + } }