Skip to content

Instantly share code, notes, and snippets.

@noman-land
Last active April 1, 2018 22:54
Show Gist options
  • Save noman-land/50f4558a232443784cef89b6e76a1f34 to your computer and use it in GitHub Desktop.
Save noman-land/50f4558a232443784cef89b6e76a1f34 to your computer and use it in GitHub Desktop.
Generic mutiplayer game contract for complex games to inherit from.
pragma solidity ^0.4.21;
contract MultiplayerGame {
uint[3] public SEMVER = [0, 1, 0];
uint public numGames;
enum ListType {
None,
Whitelist,
Blacklist
}
modifier checkPlayerPermissions(uint gameId) {
Game storage game = games[gameId];
// Can't join a game if you're on an active blacklist
if (game.enabledList == ListType.Blacklist) {
require(!game.playerStatus[msg.sender].isBlacklisted);
}
// Can't join a game unless you're on an active whitelist
if (game.enabledList == ListType.Whitelist) {
require(game.playerStatus[msg.sender].isWhitelisted);
}
_;
}
modifier gameCreatorOnly(uint gameId) {
require(msg.sender == games[gameId].players[0]);
_;
}
event PlayerJoined (uint gameId, address player);
event GameStarted (uint gameId);
struct Player {
bool isPlaying;
bool isWhitelisted;
bool isBlacklisted;
}
struct Game {
uint maxPlayers;
address[] players;
ListType enabledList;
uint whitelistSize;
address[] whitelist;
uint blacklistSize;
address[] blacklist;
mapping (address => Player) playerStatus;
uint createdBlock;
uint startBlock;
uint endBlock;
address winner;
}
mapping (uint => Game) public games;
function addToBlacklist(uint gameId, address[] players)
public
gameCreatorOnly(gameId)
{
Game storage game = games[gameId];
// Can't add players to the blacklist if it's not activated
require(game.enabledList == ListType.Blacklist);
uint playersLength = players.length;
for (uint i = 0; i < playersLength; i++) {
// Can't blacklist a player twice
require(!game.playerStatus[players[i]].isBlacklisted);
game.blacklist.push(players[i]);
game.playerStatus[players[i]].isBlacklisted = true;
}
}
function addToWhitelist(uint gameId, address[] players)
public
gameCreatorOnly(gameId)
{
Game storage game = games[gameId];
// Can't add players to the white if it's not activated
require(game.enabledList == ListType.Whitelist);
uint playersLength = players.length;
for (uint i = 0; i < playersLength; i++) {
// Can't whitelist a player twice
require(!game.playerStatus[players[i]].isWhitelisted);
game.whitelist.push(players[i]);
game.playerStatus[players[i]].isWhitelisted = true;
}
}
function getNumPlayers(uint gameId) public view returns (uint) {
return games[gameId].players.length;
}
function isBlacklisted(uint gameId, address player)
public
view
returns (bool)
{
return games[gameId].enabledList == ListType.Blacklist
&& games[gameId].playerStatus[player].isBlacklisted;
}
function isPlaying(uint gameId, address player)
public
view
returns (bool)
{
return games[gameId].playerStatus[player].isPlaying;
}
function isWhitelisted(uint gameId, address player)
public
view
returns (bool)
{
return games[gameId].enabledList == ListType.Whitelist
&& games[gameId].playerStatus[player].isWhitelisted;
}
function joinGame(uint gameId) public checkPlayerPermissions(gameId) {
Game storage game = games[gameId];
// Can only join a game that has been created
require(game.createdBlock > 0);
// Can't join a game if you've already joined
require(!isPlaying(gameId, msg.sender));
// Can't join a game that's full
require(getNumPlayers(gameId) < game.maxPlayers);
// Can't join a game if an active list hasn't been filled yet
if (game.enabledList == ListType.Whitelist) {
require(game.whitelist.length == game.whitelistSize);
} else if (game.enabledList == ListType.Blacklist) {
require(game.blacklist.length == game.blacklistSize);
}
game.players.push(msg.sender);
game.playerStatus[msg.sender].isPlaying = true;
emit PlayerJoined(gameId, msg.sender);
// Game starts when the final player joins
if (getNumPlayers(gameId) == game.maxPlayers) {
game.startBlock = block.number;
emit GameStarted(gameId);
}
}
function newGame(
uint maxPlayers,
ListType enabledList,
uint whitelistSize,
uint blacklistSize
)
public
{
// Games must have more than one player
require(maxPlayers > 1);
if (enabledList == ListType.Whitelist) {
// If whitelist is activated, it must have a size
// and blacklist must be empty
require(whitelistSize > 0 && blacklistSize == 0);
// Whitelist doesn't need to include game creator and
// so can be one less than the max number of players
require(whitelistSize >= maxPlayers - 1);
} else if (enabledList == ListType.Blacklist) {
// If blacklist is activated, it must have a size
// and whitelist must be empty
require(blacklistSize > 0 && whitelistSize == 0);
} else {
// If no list is activated, the lists can't have a size
require(whitelistSize == 0 && blacklistSize == 0);
}
numGames = numGames + 1;
Game storage game = games[numGames];
game.maxPlayers = maxPlayers;
game.players.push(msg.sender);
game.playerStatus[msg.sender].isPlaying = true;
game.createdBlock = block.number;
game.enabledList = enabledList;
game.whitelistSize = whitelistSize;
game.blacklistSize = blacklistSize;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment