Last active
April 1, 2018 22:54
-
-
Save noman-land/50f4558a232443784cef89b6e76a1f34 to your computer and use it in GitHub Desktop.
Generic mutiplayer game contract for complex games to inherit from.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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