diff --git a/onchain/manifests/dev/base/abis/contracts/starkludo-GameActions-72b46dc4.json b/onchain/manifests/dev/base/abis/contracts/starkludo-GameActions-72b46dc4.json index 953e1bb..6520184 100644 --- a/onchain/manifests/dev/base/abis/contracts/starkludo-GameActions-72b46dc4.json +++ b/onchain/manifests/dev/base/abis/contracts/starkludo-GameActions-72b46dc4.json @@ -349,6 +349,10 @@ "name": "game_mode", "type": "starkludo::models::game::GameMode" }, + { + "name": "game_status", + "type": "starkludo::models::game::GameStatus" + }, { "name": "player_green", "type": "core::felt252" @@ -400,6 +404,30 @@ ], "outputs": [], "state_mutability": "external" + }, + { + "type": "function", + "name": "join_game", + "inputs": [ + { + "name": "game_id", + "type": "core::integer::u64" + }, + { + "name": "player_color", + "type": "core::felt252" + }, + { + "name": "username", + "type": "core::felt252" + } + ], + "outputs": [ + { + "type": "starkludo::models::game::Game" + } + ], + "state_mutability": "external" } ] }, diff --git a/onchain/manifests/dev/base/contracts/starkludo-GameActions-72b46dc4.toml b/onchain/manifests/dev/base/contracts/starkludo-GameActions-72b46dc4.toml index 436863b..a323d19 100644 --- a/onchain/manifests/dev/base/contracts/starkludo-GameActions-72b46dc4.toml +++ b/onchain/manifests/dev/base/contracts/starkludo-GameActions-72b46dc4.toml @@ -1,6 +1,6 @@ kind = "DojoContract" -class_hash = "0x4cecefc87acb36b188cec659cfde8d7cbfafaf8684297f7d66cadd573cbfec5" -original_class_hash = "0x4cecefc87acb36b188cec659cfde8d7cbfafaf8684297f7d66cadd573cbfec5" +class_hash = "0x4822d5336e093bd5060f977312516677c87cda7cc86ebac5941cf148054a2bf" +original_class_hash = "0x4822d5336e093bd5060f977312516677c87cda7cc86ebac5941cf148054a2bf" base_class_hash = "0x0" abi = "manifests/dev/base/abis/contracts/starkludo-GameActions-72b46dc4.json" reads = [] diff --git a/onchain/src/systems/game_actions.cairo b/onchain/src/systems/game_actions.cairo index 655f9cd..91d15a2 100644 --- a/onchain/src/systems/game_actions.cairo +++ b/onchain/src/systems/game_actions.cairo @@ -1,8 +1,9 @@ -use starkludo::models::{game::{Game, GameTrait, GameMode}, player::{Player}}; +use starkludo::models::{game::{Game, GameTrait, GameMode, GameStatus}, player::{Player}}; use starknet::{ContractAddress, get_block_timestamp}; use core::poseidon::PoseidonTrait; use core::hash::HashStateTrait; + #[dojo::interface] trait IGameActions { fn create( @@ -18,14 +19,18 @@ trait IGameActions { fn restart(ref world: IWorldDispatcher, game_id: u64); fn terminate_game(ref world: IWorldDispatcher, game_id: u64); fn invite_player(ref world: IWorldDispatcher, game_id: u64, player_username: felt252); + fn join_game( + ref world: IWorldDispatcher, game_id: u64, player_username: felt252, player_color: felt252 + ); } + #[dojo::contract] mod GameActions { // use Zero; // use core::num::traits::Zero; use core::array::ArrayTrait; - use super::{IGameActions, Game, GameTrait, GameMode, Player}; + use super::{IGameActions, Game, GameTrait, GameMode, Player, GameStatus}; use starknet::{ContractAddress, get_caller_address, get_block_timestamp}; #[abi(embed_v0)] @@ -38,7 +43,7 @@ mod GameActions { player_yellow: felt252, player_blue: felt252, player_red: felt252, - number_of_players: u8 + number_of_players: u8, ) -> Game { // Get the current block timestamp let id = get_block_timestamp(); @@ -156,6 +161,42 @@ mod GameActions { // Update the game state in the world set!(world, (game)); } + + + fn join_game( ref world: IWorldDispatcher, game_id: u64, player_username: felt252, player_color: felt252 ) { + let mut game: Game = get!(world, game_id, (Game)); + + assert(game.game_status == GameStatus::Waiting, 'Game is not pending'); + + let mut player: Player = get!(world, player_username, (Player)); + assert(player.owner != 0.try_into().unwrap(), 'Player does not exist'); + let players = array![ + game.player_green, game.player_yellow, game.player_blue, game.player_red + ]; + let players_span = players.span(); + let mut i = 0; + while i < 4 { + assert(players_span[i] != @player_username, 'Player already in game'); + i += i; + }; + match player_color { + 0 => game.player_green = player_username, + 1 => game.player_yellow = player_username, + 2 => game.player_blue = player_username, + 3 => game.player_red = player_username, + _ => panic!("Invalid player color") + } + + // Update game status if all players have joined + if game.player_green != 0 + && game.player_yellow != 0 + && game.player_blue != 0 + && game.player_red != 0 { + game.game_status = GameStatus::Ongoing; + } + + set!(world, (game)); + } } } diff --git a/onchain/src/tests/test_game.cairo b/onchain/src/tests/test_game.cairo index 8d0f8a0..26e52b6 100644 --- a/onchain/src/tests/test_game.cairo +++ b/onchain/src/tests/test_game.cairo @@ -214,5 +214,45 @@ mod tests { // // Assert that the player was invited. if false then player was not invited // assert(is_player_invited, Errors::INVALID_PLAYER); } + + + #[test] + #[ignore] + fn test_join_game() { + let caller = contract_address_const::<'Benjamin'>(); + let player_red = 'player_red'; + let player_blue = 'player_blue'; + let player_yellow = 'player_yellow'; + let player_green = 'player_green'; + let number_of_players = 4; + let game_mode: GameMode = GameMode::MultiPlayer; + testing::set_account_contract_address(caller); + testing::set_contract_address(caller); + + let (game, game_actions, world, _) = create_and_setup_game( + game_mode, number_of_players, player_red, player_blue, player_yellow, player_green + ); + + let game_id: u64 = game.id; + let new_player = 'player_red'; + let player_color: felt252 = 0; + + // Check game status before joining + let game_before_join = get!(world, game_id, Game); + assert_eq!( + game_before_join.game_status, + GameStatus::Waiting, + "Game should be in Waiting status before joining" + ); + + // Attempt to join the game + game_actions.join_game(game_id, new_player, player_color); + + // Verify the game state after joining + let updated_game = get!(world, game_id, Game); + assert_eq!( + updated_game.player_green, new_player.into(), "Player should have joined the game" + ); + } }