Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/constants.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub mod constants {
pub const INIT_STAMINA: u8 = 100;

pub const ITEMS_COUNTER_ID: felt252 = 'ITEMS_COUNTER_ID';
pub const RECIPES_COUNTER_ID: felt252 = 'RECIPES_COUNTER_ID';
pub const STORAGE_FLAG: u32 = 999;

// const EFFECT_ARMOR: felt252 = 'armor';
Expand Down
1 change: 1 addition & 0 deletions src/models/Item.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub struct Item {
pub cooldown: u8,
pub energyCost: u8,
pub isPlugin: bool,
pub enabled: bool,
}

#[derive(Drop, Serde)]
Expand Down
17 changes: 13 additions & 4 deletions src/models/Recipe.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,17 @@
#[dojo::model]
pub struct Recipe {
#[key]
pub item1_id: u32,
#[key]
pub item2_id: u32,
pub id: u32,
pub item_ids: Array<u32>,
pub item_amounts: Array<u32>,
pub result_item_id: u32,
}
pub enabled: bool,
}

#[derive(Drop, Serde)]
#[dojo::model]
pub struct RecipesCounter {
#[key]
pub id: felt252,
pub count: u32,
}
132 changes: 80 additions & 52 deletions src/systems/actions.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub trait IActions<T> {
fn move_item_from_storage_to_shop(ref self: T, storage_item_id: u32);
fn move_item_from_shop_to_inventory(ref self: T, item_id: u32, x: u32, y: u32, rotation: u32);
fn move_item_from_inventory_to_shop(ref self: T, inventory_item_id: u32);
fn craft_item(ref self: T, recipe_id: u32, storage_ids: Array<u32>);
}

// TODO: rename the count filed in counter model
Expand All @@ -31,6 +32,7 @@ mod actions {
use super::{IActions, WMClass};
use starknet::ContractAddress;
use core::dict::Felt252Dict;
use core::array::Array;
use core::bytes_31::bytes31;

use starknet::{get_caller_address, get_block_timestamp};
Expand All @@ -44,7 +46,8 @@ mod actions {
Character::{Characters, NameRecord},
Shop::Shop,
Fight::{BattleLog, BattleLogCounter},
Game::GameConfig
Game::GameConfig,
Recipe::Recipe
};

use warpack_masters::items::{Backpack, Pack};
Expand Down Expand Up @@ -309,37 +312,14 @@ mod actions {
}

fn move_item_from_inventory_to_storage(ref self: ContractState, inventory_item_id: u32) {
let mut world = self.world(@"Warpacks");

let player = get_caller_address();

// check if the player has joined the matching battle
self._check_if_player_has_joined_a_matched_battle(player);

let itemId = self._remove_item_from_inventory(player, inventory_item_id);
let item_id = self._remove_item_from_inventory(player, inventory_item_id);

let mut storageCounter: CharacterItemsStorageCounter = world.read_model(player);
let mut count = storageCounter.count;
loop {
if count == 0 {
break;
}

let mut storageItem: CharacterItemStorage = world.read_model((player, count));
if storageItem.itemId == 0 {
storageItem.itemId = itemId;
world.write_model(@storageItem);
break;
}

count -= 1;
};

if count == 0 {
storageCounter.count += 1;
world.write_model(@CharacterItemStorage { player, id: storageCounter.count, itemId: itemId, });
world.write_model(@CharacterItemsStorageCounter { player, count: storageCounter.count });
}
self._add_item_to_storage(player, item_id);
}

fn move_item_within_inventory(ref self: ContractState, inventory_item_id: u32, x: u32, y: u32, rotation: u32) {
Expand All @@ -353,36 +333,11 @@ mod actions {
}

fn move_item_from_shop_to_storage(ref self: ContractState, item_id: u32) {
let mut world = self.world(@"Warpacks");

let player = get_caller_address();

self._buy_item(player, item_id);

let mut storageCounter: CharacterItemsStorageCounter = world.read_model(player);
let mut count = storageCounter.count;
let mut isUpdated = false;
loop {
if count == 0 {
break;
}

let mut storageItem: CharacterItemStorage = world.read_model((player, count));
if storageItem.itemId == 0 {
storageItem.itemId = item_id;
isUpdated = true;
world.write_model(@storageItem);
break;
}

count -= 1;
};

if isUpdated == false {
storageCounter.count += 1;
world.write_model(@CharacterItemStorage { player, id: storageCounter.count, itemId: item_id, });
world.write_model(@CharacterItemsStorageCounter { player, count: storageCounter.count });
}
self._add_item_to_storage(player, item_id);
}

fn move_item_from_storage_to_shop(ref self: ContractState, storage_item_id: u32) {
Expand Down Expand Up @@ -414,6 +369,52 @@ mod actions {
let item_id = self._remove_item_from_inventory(player, inventory_item_id);
self._sell_item(player, item_id);
}

fn craft_item(
ref self: ContractState, recipe_id: u32, storage_ids: Array<u32>
) {
let mut world = self.world(@"Warpacks");

let player = get_caller_address();

let recipe: Recipe = world.read_model(recipe_id);
assert(recipe.enabled, 'recipe is not enabled');

let item_ids_len = recipe.item_ids.len();
assert(item_ids_len > 0, 'must have at least one item');
assert(item_ids_len == recipe.item_amounts.len(), 'must the same length');

let mut required_items: Felt252Dict<u32> = Default::default();
for i in 0..item_ids_len {
let item_id = *recipe.item_ids[i];
let item_amount = *recipe.item_amounts[i];
required_items.insert(item_id.into(), item_amount);
};

let storage_ids_len = storage_ids.len();
assert(storage_ids_len > 0, 'must have at least one item');

for i in 0..storage_ids_len {
let storage_id = *storage_ids[i];
let mut storage_item: CharacterItemStorage = world.read_model((player, storage_id));
assert(storage_item.itemId != 0, 'item not owned');

let required_item_amount = required_items.get(storage_item.itemId.into());
if (required_item_amount > 0) {
required_items.insert(storage_item.itemId.into(), required_item_amount - 1);
storage_item.itemId = 0;
world.write_model(@storage_item);
}
};

for i in 0..item_ids_len {
let item_id = *recipe.item_ids[i];

assert(required_items.get(item_id.into()) == 0, 'item not enough');
};

self._add_item_to_storage(player, recipe.result_item_id);
}
}

#[generate_trait]
Expand Down Expand Up @@ -843,5 +844,32 @@ mod actions {

world.write_model(@playerChar);
}

fn _add_item_to_storage(ref self: ContractState, player: ContractAddress, item_id: u32) {
let mut world = self.world(@"Warpacks");

let mut storageCounter: CharacterItemsStorageCounter = world.read_model(player);
let mut count = storageCounter.count;
loop {
if count == 0 {
break;
}

let mut storageItem: CharacterItemStorage = world.read_model((player, count));
if storageItem.itemId == 0 {
storageItem.itemId = item_id;
world.write_model(@storageItem);
break;
}

count -= 1;
};

if count == 0 {
storageCounter.count += 1;
world.write_model(@CharacterItemStorage { player, id: storageCounter.count, itemId: item_id });
world.write_model(@storageCounter);
}
}
}
}
1 change: 1 addition & 0 deletions src/systems/item.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ mod item_system {
cooldown,
energyCost,
isPlugin,
enabled: true,
};

world.write_model(@item);
Expand Down
70 changes: 26 additions & 44 deletions src/systems/recipe.cairo
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
#[starknet::interface]
pub trait IRecipe<T> {
fn add_recipe(
ref self: T, item1_id: u32, item2_id: u32, result_item_id: u32
);
fn craft_item(
ref self: T, storage_item_id1: u32, storage_item_id2: u32
ref self: T, item_ids: Array<u32>, item_amounts: Array<u32>, result_item_id: u32
);
}

Expand All @@ -14,68 +11,53 @@ mod recipe_system {

use starknet::{get_caller_address};
use warpack_masters::models::{
CharacterItem::CharacterItemStorage,
Item::Item,
Recipe::Recipe,
Recipe::{Recipe, RecipesCounter},
};
use warpack_masters::constants::constants::{RECIPES_COUNTER_ID};

use dojo::model::{ModelStorage};
use dojo::world::{IWorldDispatcherTrait};

#[abi(embed_v0)]
impl RecipeImpl of IRecipe<ContractState> {
fn add_recipe(
ref self: ContractState, item1_id: u32, item2_id: u32, result_item_id: u32
ref self: ContractState, item_ids: Array<u32>, item_amounts: Array<u32>, result_item_id: u32
) {
let mut world = self.world(@"Warpacks");

let player = get_caller_address();
assert(world.dispatcher.is_owner(0, player), 'player not world owner');

let item1: Item = world.read_model(item1_id);
assert(item1.height != 0, 'item1 does not exist');
let item2: Item = world.read_model(item2_id);
assert(item2.height != 0, 'item2 does not exist');
let item_ids_len = item_ids.len();
assert(item_ids_len > 0, 'must have at least one item');
assert(item_ids_len == item_amounts.len(), 'must the same length');

for i in 0..item_ids_len {
let item_id = *item_ids[i];
let item_amount = *item_amounts[i];
assert(item_amount > 0, 'amount must be greater than 0');

let item: Item = world.read_model(item_id);
assert(item.enabled, 'item is not enabled');
};

// make constructor
let result_item: Item = world.read_model(result_item_id);
assert(result_item.height != 0, 'result item does not exist');
assert(result_item.enabled, 'result item is not enabled');

let mut recipes_counter: RecipesCounter = world.read_model(RECIPES_COUNTER_ID);
let new_id = recipes_counter.count + 1;
recipes_counter.count = new_id;

world.write_model(@Recipe {
item1_id,
item2_id,
id: new_id,
item_ids,
item_amounts,
result_item_id,
enabled: true,
});

if item1_id != item2_id {
world.write_model(@Recipe {
item1_id: item2_id,
item2_id: item1_id,
result_item_id,
});
}
}

fn craft_item(
ref self: ContractState, storage_item_id1: u32, storage_item_id2: u32
) {
let mut world = self.world(@"Warpacks");

let player = get_caller_address();

let mut storageItem1: CharacterItemStorage = world.read_model((player, storage_item_id1));
assert(storageItem1.itemId != 0, 'item not owned');

let mut storageItem2: CharacterItemStorage = world.read_model((player, storage_item_id2));
assert(storageItem2.itemId != 0, 'item not owned');

let recipe: Recipe = world.read_model((storageItem1.itemId, storageItem2.itemId));
assert(recipe.result_item_id != 0, 'No valid recipe found');

storageItem1.itemId = recipe.result_item_id;
storageItem2.itemId = 0;
world.write_model(@storageItem1);
world.write_model(@storageItem2);
world.write_model(@recipes_counter);
}
}
}
Loading
Loading