0

I need to create an online game using solidity. The games have games within them with each game having their respective players. it can be likened to a battle royale on a FPS game where there are various battle royales going on simultaneously within the game with their respective participants. I tried using an array within a struct to keep record of the games. However, I have been facing error after error trying to do this.

The Struct:

struct Game {
        address[] participants;
        uint amountRequired;
        uint Duration;
        uint id;
        bool ended;
        uint createdTime;
    } 

The function to create the game:

function CreateGame(uint amountRequired, string memory timeoption) public restricted{
        setGameDuration(timeoption);
        gameid++;

        Game memory newGame = Game({
            participants: address[] participants,
            amountRequired: amountRequired,
            Duration: gametime,
            id: gameid,
            ended: false,
            createdTime: block.timestamp

        });
        
    }
TylerH
  • 20,799
  • 66
  • 75
  • 101
Chukwujike
  • 11
  • 4

1 Answers1

0

You need to initialize the array on a separate line, and then pass it to the struct. See the _participants variable in the snippet:

pragma solidity ^0.8;

contract MyContract {
    struct Game {
        address[] participants;
        uint amountRequired;
        uint Duration;
        uint id;
        bool ended;
        uint createdTime;
    }

    // create a storage mapping of value type `Game`
    // id => Game
    mapping(uint => Game) public games;

    function CreateGame(uint amountRequired, string memory timeoption) public {
        // dummy values
        address[] memory _participants; // empty array by default
        uint gametime = 1;
        uint gameid = 1;

        Game memory newGame = Game({
            participants: _participants,
            amountRequired: amountRequired,
            Duration: gametime,
            id: gameid,
            ended: false,
            createdTime: block.timestamp
        });

        // store the `memory` value into the `storage` mapping
        games[gameid] = newGame;
    }

    function addParticipant(uint gameId, address participant) public {
        require(games[gameId].createdTime > 0, "This game does not exist");
        games[gameId].participants.push(participant);
    }
}

If you want to set some participants in the code (not passed from an argument), working with dynamic array in memory is a bit tricky. See this answer for more info and an example.

Edit: To add participants to the array in a separate function, you need to store the Game in a storage variable first. See the games mapping in my update snippet. Then you can .push() into the storage array from a separate function.

Petr Hejda
  • 40,554
  • 8
  • 72
  • 100
  • Thank you, Petr for responding. This is very useful. I don't quite understand how to add players to the arrays. I've gone through the referenced post and I am more confused than not. The players can enter the games by calling a function. The function then stores their addresses until the game is over. – Chukwujike Mar 18 '22 at 10:04
  • I am also looking for an alternative solution which involves mapping the game id to an array of addresses. mapping (uint => address payable []) public participants; and then participants(Game.id) = new address payable[ ]; participants(Game.id).push(msg.sender). – Chukwujike Mar 18 '22 at 10:10
  • @Chukwujike See the edited answer, there's an example of adding participants to the game from a separate function. – Petr Hejda Mar 18 '22 at 12:49
  • I implemented your solution in the Code and kept getting the error: TypeError: Invalid type for argument in function call. Invalid implicit conversion from address[] memory to address payable[] memory requested. – Chukwujike Mar 19 '22 at 12:22
  • @Chukwujike I don't see anything that would require `payable` in the answer code, so this error message is not directly related to it. Anyway, when using `transfer()` and function in Solidity 0.8+, you need to typecast the `msg.sender` (type `address`) to `address payable` by using `payable(msg.sender).transfer(amount);`. See [this answer](https://stackoverflow.com/a/66799729/1693192) for more info... Or it's also possible that you changed the `participants` definition to `address payable[]` - then you also need to change the type of the argument to `address payable[]` as well. – Petr Hejda Mar 19 '22 at 13:01