Skip to content
Open
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
39 changes: 39 additions & 0 deletions app/classes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
var uuid = require('uuid'),
constants = require('../constants'),
words = require('../words');

exports.Interaction = function() {
this.id = uuid.v4();
this.isSsl = false;
this.isTor = false;
this.message = null; // The message that initiated this interaction
this.responses = []; // The messages that have been sent as a response to this interaction
this.socket = null; // The socket that initiated this interaction
};

exports.Rumor = function(gameId) {
this.generateText = function() {
var rumorText = "";
for(var x = 0 ; x < 2 ; ++x) {
var word = words.words[Math.floor(Math.random() * words.words.length)];
rumorText += ((x===0)?"":" ") + word;
}
return rumorText;
};

this.gameId = gameId;
this.id = uuid.v4();
this.truthStatus = "";
this.publicationStatus = "";
this.sourceId = "";
this.text = this.generateText();
this.transfers = [];

this.getPlayerTruthStatus = function(player) {
if (this.publicationStatus == constants.RUMOR_PUBLICATIONSTATUS_PUBLISHED || this.sourceId === player.id) {
return this.truthStatus;
} else {
return constants.RUMOR_TRUTHSTATUS_UNKNOWN;
}
};
};
10 changes: 10 additions & 0 deletions app/handlers/error.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
var payloads = require('../../payloads');
var messageTypes = require('../../message-types');

// Functions
module.exports = function (message, socket) {
var error = new payloads.ErrorPayload(message);
socket.emit('error', {
payload: error.getPayload()
});
};
33 changes: 33 additions & 0 deletions app/handlers/heartbeat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
var constants = require('../../constants'),
payloads = require('../../payloads'),
locales = require('../../locales'),
error = require('./error'),
messageSender = require('./messageSender'),
gameRepository = require('../repositories/game'),
messageTypes = require('../../message-types');

exports.handle = function(payload, interaction) {
var socket = interaction.socket;
var count = payload.data.count;
var game = gameRepository.get(payload.data.gameId, function (err, game) {
if (err) {
throw err;
}

// Did the game end?
if (game.phase === 'COMPLETED') {
return;
}

// Start the next heartbeat
return setTimeout(function() {
var heartbeatPayload = new payloads.StorytellerHeartbeatOutPayload(++count);
messageSender.send(
heartbeatPayload.getPayload(),
socket,
interaction);
}, constants.TICK_HEARTBEAT);
});

};

39 changes: 39 additions & 0 deletions app/handlers/messageSender.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
var config = require('../../config');
var serverSocket = require('socket.io-client')(config.socketIoHost + ':' + config.socketIoPort);

exports.sendToServer = function(payload) {
var message = {
payload: payload
};

serverSocket.emit('message', message);
};

exports.send = function(payload, sockets, interaction) {
if (!(sockets instanceof Array)) {
sockets = [sockets];
}

var message = {
payload: payload
};

// Add to the interaction
if(interaction) {
interaction.responses.push(message);
message.interactionId = interaction.id;
}

// TODO: Snoop the interaction
if(interaction) {
// var interceptIn = new payloads.SnooperInterceptInPayload(interaction);
// exports.routeMessage(
// constants.COMMUNICATION_TARGET_SNOOPER,
// interceptIn.getPayload(),
// constants.COMMUNICATION_SOCKET_SERVER);
}

for (var socket in sockets) {
sockets[socket].emit('message', message);
}
};
5 changes: 5 additions & 0 deletions app/handlers/newspaper/publish.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// TODO: actually do something

exports.handle = function (data, interaction) {
return;
};
30 changes: 30 additions & 0 deletions app/handlers/router.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
var classes = require('../classes'),
constants = require('../../constants'),
payloads = require('../../payloads'),
gameState = require('../lib/gameState'),
routingTable = require('./routingTable'),
logger = require('../lib/logger').logger;

exports.receiveMessage = function(message, socket) {
if(!message.payload || !message.payload.type) {
logger.info("Invalid payload received " + JSON.stringify(message));
return; // Invalid payload
}

// Set up metadata about the message
if(gameState.getInteractionById(message.interactionId)) {
logger.info("Duplicate interaction received " + message.interactionId);
return; // Duplicate interaction
}
// Build the interaction
var interaction = new classes.Interaction();
interaction.id = message.interactionId?message.interactionId:interaction.id;
interaction.message = message;
interaction.isTor = message.isTor?true:false;
interaction.isSsl = message.isSsl?true:false;
interaction.socket = socket;
gameState.storeInteraction(interaction);
message.interactionId = interaction.id;

routingTable[message.payload.type].handle(message.payload, interaction);
};
24 changes: 24 additions & 0 deletions app/handlers/routingTable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
var messageTypes = require('../../message-types'),
heartbeat = require('./heartbeat'),
start = require('./storyteller/startGame'),
join = require('./storyteller/joinGame'),
tick = require('./storyteller/tick'),
ircSubpoena = require('./storyteller/subpoenaIrc'),
emailSubpoena = require('./storyteller/subpoenaEmail'),
kill = require('./storyteller/kill'),
end = require('./storyteller/end'),
publish = require('./newspaper/publish'),
table = {};

table[messageTypes.STORYTELLER_HEARTBEATPONG] = heartbeat;
table[messageTypes.STORYTELLER_JOIN] = join;
table[messageTypes.STORYTELLER_START] = start;
table[messageTypes.STORYTELLER_TICK] = tick;
table[messageTypes.STORYTELLER_IRCSUBPOENA] = ircSubpoena;
table[messageTypes.STORYTELLER_EMAILSUBPOENA] = emailSubpoena;
table[messageTypes.STORYTELLER_KILL] = kill;
table[messageTypes.STORYTELLER_END] = end;

table[messageTypes.NEWSPAPER_PUBLISH] = publish;

module.exports = table;
22 changes: 22 additions & 0 deletions app/handlers/storyteller/end.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
var gameState = require('../../lib/gameState'),
payloads = require('../../../payloads'),
locales = require('../../../locales'),
messageSender = require('../messageSender'),
gameRepository = require('../../repositories/game'),
logger = require('../../lib/logger').logger;

exports.handle = function (data, interaction) {
var game = gameState.getGameById(data.data.gameId);
game.phase = 'COMPLETED';
gameRepository.update(game, game.id, function (err, game) {
if (err) {
logger.error(err);
}
});

// That's all folks!
var announcementOut = new payloads.StorytellerAnnouncementOutPayload(locales[game.locale].messages.storyteller.GAMEOVER);
messageSender.send(
announcementOut.getPayload(),
gameState.getSocketsByGameId(game.id));
};
69 changes: 69 additions & 0 deletions app/handlers/storyteller/joinGame.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
var constants = require('../../../constants'),
payloads = require('../../../payloads'),
locales = require('../../../locales'),
error = require('../error'),
messageSender = require('../messageSender'),
gameRepository = require('../../repositories/game'),
gameState = require('../../lib/gameState'),
userRepository = require('../../repositories/user'),
async = require('async'),
logger = require('../../lib/logger').logger;

exports.handle = function(payload, interaction) {
var socket = interaction.socket;
async.parallel([
function(cb) {
gameRepository.get(payload.data.gameId, cb);
},
function(cb) {
userRepository.get(payload.data.playerId, cb);
}
], function(error, results) {
if (error) {
throw error;
}
var game = results[0];
var player = results[1];

if (!gameState.getGameById(game.id)) {
gameState.storeGame(game);
}

// Tell the player who is in the game
var joinOut = null;
for(var x in gameState.getGameById(game.id).players) {
// TODO: replace with state replay
var otherPlayer = gameState.getGameById(game.id).players[x];
joinOut = new payloads.StorytellerJoinOutPayload(otherPlayer);
messageSender.send(
joinOut.getPayload(),
socket,
interaction);
}

// Announce the entrance of the player
joinOut = new payloads.StorytellerJoinOutPayload(player);

messageSender.send(
joinOut.getPayload(),
gameState.getSocketsByGame(game)
);

gameState.storeSocket(socket, player.id);
gameState.addPlayerToGame(game.id, player, socket);

// FIXME: do not hard code length
if(gameState.getGameById(game.id).players.length == 8) {
var startOut = new payloads.StorytellerStartInPayload(game);
messageSender.sendToServer(
startOut.getPayload());
}

// TODO: Have them join IRC
// var joinIn = new payloads.IrcJoinInPayload(player.name);
// communication.routeMessage(
// constants.COMMUNICATION_TARGET_IRC,
// joinIn.getPayload(),
// socket);
});
};
56 changes: 56 additions & 0 deletions app/handlers/storyteller/kill.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
var gameState = require('../../lib/gameState'),
error = require('../error'),
locales = require('../../../locales'),
messageSender = require('../messageSender'),
constants = require('../../../constants'),
payloads = require('../../../payloads');

exports.handle = function (data, interaction) {
var socket = interaction.socket;
var playerRole = gameState.getRoleByPlayerId(data.data.playerId);
var killer = gameState.getPlayerBySocketId(socket.id);
var killerRole = gameState.getRoleByPlayerId(data.data.playerId);
var game = gameState.getGameById(data.data.gameId);

if(!playerRole) {
return error(locales[socket.locale].errors.storyteller.KILL_NOBODY, socket);
}

if(killerRole != constants.PLAYER_ROLE_AGENT) {
return error(locales[socket.locale].errors.storyteller.KILL_ILLEGAL, socket);
}

var killOut = new payloads.StorytellerKillOutPayload({ id : data.data.playerId });
messageSender.send(
killOut.getPayload(),
gameState.getSocketsByGameId(game.id));

// Check victory conditions
var endIn = null;
var announcementOut = null;
if(playerRole == constants.PLAYER_ROLE_ACTIVIST) {
announcementOut = new payloads.StorytellerAnnouncementOutPayload(locales[game.locale].messages.storyteller.VICTORY_GOVERNMENT_ACTIVIST);
messageSender.send(
announcementOut.getPayload(),
gameState.getSocketsByGameId(game.id));

endIn = new payloads.StorytellerEndInPayload(game);
messageSender.sendToServer(endIn.getPayload());
} else if(playerRole == constants.PLAYER_ROLE_JOURNALIST) {
announcementOut = new payloads.StorytellerAnnouncementOutPayload(locales[game.locale].messages.storyteller.VICTORY_GOVERNMENT_JOURNALIST);
messageSender.send(
announcementOut.getPayload(),
gameState.getSocketsByGameId(game.id));

endIn = new payloads.StorytellerEndInPayload(game);
messageSender.routeMessage(endIn.getPayload());
} else {
announcementOut = new payloads.StorytellerAnnouncementOutPayload(locales[game.locale].messages.storyteller.VICTORY_ACTIVISTS_KILLING);
messageSender.send(
announcementOut.getPayload(),
gameState.getSocketsByGameId(game.id));

endIn = new payloads.StorytellerEndInPayload(game);
messageSender.sendToServer(endIn.getPayload());
}
};
21 changes: 21 additions & 0 deletions app/handlers/storyteller/leaveGame.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
exports.handle = function(payload, interaction) {
// TODO: implement ability to leave game

// Do the Mario!

// Swing your arms from side to side
// Come on, it's time to go!
// Do the Mario!
// Take one step, and then again.
// Let's do the Mario, all together now!
// You've got it!
// It's the Mario!
// Do the Mario!
// Swing your arms from side to side
// Come on, it's time to go!
// Do the Mario!
// Take one step, and then again.
// Let's do the Mario, all together now!

// Come on now, just like that!
};
Loading