playship_ludo_pseudo_quick
Version:
Server side neutrino plugin code for ludo game
285 lines (270 loc) • 10.7 kB
JavaScript
const logger = require('../utils/playshipUtils').getLogger();
const enums = require('../utils/enums');
const gameLogic = require('./logic');
const events = enums.NEW_EVENTS
const eventObjs = require('../utils/newGameEvent')
const {
_gameObjById,
_getMeta,
_setPlayerProp,
_getPlayerProp,
_setGameProp,
_getGameProp,
_isHighestScore,
_getGameTimeLeft,
_isForfeitTurnCountBreached,
_publishGameDiceRollsInfo,
_setPLayerInitGameScore
} = require('../utils/utils');
const PLAYER_PROPS = enums.PLAYER_PROPS;
const GAME_PROPS = enums.GAME_PROPS;
const OBJECT_PROPS = enums.OBJECT_PROPS;
const gameStarted = function(game) {
const gameKey = game.getId();
let numPlayers = game.getNumberOfPlayers();
let meta = _getMeta(game);
let gameTime = meta.selectedPawn[numPlayers];
logger.info({key: gameKey}, 'game time %s for max players %s', gameTime,
numPlayers);
let ts = Date.now();
let gameTimerEndTs = ts + gameTime;
game.sendTip(game.getPlayerSeating()[0], 16);
_setGameProp(game, GAME_PROPS.GAME_TIMER_END_TS, gameTimerEndTs);
game.syncGameStateServVars();
};
const mapToLoad = function(game, initialMaps) {
const gameKey = game.getId();
let playerCount = game.getNumberOfPlayers();
let meta = _getMeta(game);
let version = parseInt(meta.mapVersion) || 3;
logger.debug(gameKey,'map version ,', version);
let map = null;
for (let i = 0; i < initialMaps.length; i++) {
if (playerCount === parseInt(initialMaps[i].maxPlayer)
&& version === parseInt(initialMaps[i].version)) {
logger.debug(gameKey,'map selected ,', initialMaps[i]);
map = initialMaps[i];
break;
}
}
return map;
};
const startGame = function(game, cb) {
initGameProps(game);
initPlayerProps(game);
gameLogic.turnInit(game);
gameLogic.issueTurnStartSavePoint(game);
initRevPosMap(game);
cb(null);
};
function initGameProps(game) {
let meta = _getMeta(game);
let isTournament = game.getBattleType() === enums.BATTLE_TYPES.TOURNAMENT
game.setGameProp('maxMissMoves', meta.maxMissMoves);
game.setGameProp('maxPieceKills', meta.maxPieceKills);
game.setGameProp('playerSeating', game.getPlayerSeating());
game.setGameProp('maxMovesPerPlayer', meta.maxMovesPerPlayer);
game.setGameProp('isDiceRevealed', false);
game.setGameProp('autoRollTrigBeforeTurnEndMill',
meta.autoRollTrigBeforeTurnEndMill);
let numPlayers = game.getNumberOfPlayers();
let gameTime = meta.selectedPawn[numPlayers];
_setGameProp(game, GAME_PROPS.GAME_TIMER, gameTime);
_setGameProp(game, GAME_PROPS.GAME_TIMER_REMAINING, gameTime);
_setGameProp(game, GAME_PROPS.TOTAL_EXTRA_TIME, isTournament ? 0 : meta.extraTime);
_setGameProp(game, GAME_PROPS.IS_GAME_PAUSED,false);
_setGameProp(game, GAME_PROPS.IS_FORFEIT_FRAUD_BY_ANY_PLAYER,false);
_setGameProp(game, GAME_PROPS.NO_POSSIBLE_MOVE,true);
_setGameProp(game, GAME_PROPS.IS_TURN_COMPLETED, false);
}
function initRevPosMap(game) {
let objIds = game.getAllObjIds();
let objIdList = [];
for (let objId of objIds) {
let obj = _gameObjById(game, objId);
objIdList.push({id: objId, posKey: obj._get(OBJECT_PROPS.PATH_INDEX)});
}
game.initCollisionMap(objIdList);
for (let objId of objIds) {
let obj = _gameObjById(game, objId);
obj._set(OBJECT_PROPS.PATH_INDEX, null);
}
}
function getColours(playerCount) {
switch (parseInt(playerCount)) {
case 2 :
return ['greenPiece', 'bluePiece'];
case 3 :
return ['greenPiece', 'yellowPiece', 'bluePiece'];
case 4 :
return ['greenPiece', 'yellowPiece', 'bluePiece', 'redPiece'];
}
}
function initPlayerProps(game) {
let i = 0;
const meta = _getMeta(game);
let isTournament = game.getBattleType() === enums.BATTLE_TYPES.TOURNAMENT
let shuffledColors = getColours(game.getNumberOfPlayers());
let users = []// for random color assignment
for (let p of game.getPlayerSeating()) {
const pieceType = shuffledColors[i]
_setPlayerProp(game, p, PLAYER_PROPS.KILLS, 0);
_setPlayerProp(game, p, PLAYER_PROPS.GOT_KILLED,0);
_setPlayerProp(game, p, PLAYER_PROPS.TOTAL_TIME_PLAYED,0)
_setPlayerProp(game, p, PLAYER_PROPS.ASCEND_COUNT, 0);
_setPlayerProp(game, p, PLAYER_PROPS.COLOR, pieceType);
_setPlayerProp(game, p, PLAYER_PROPS.MISS_MOVES, 0);
_setPlayerProp(game, p, PLAYER_PROPS.TURN_COUNT, 0);
_setPlayerProp(game, p, PLAYER_PROPS.ARE_PAWNS_DESTROYED, false);
_setPlayerProp(game, p, PLAYER_PROPS.KILL_TYPES, {types: []});
_setPlayerProp(game, p, PLAYER_PROPS.CONSECUTIVE_SIXES, 0);
_setPlayerProp(game, p, PLAYER_PROPS.AUTO_ROLL_COUNT,0)
_setPlayerProp(game, p, PLAYER_PROPS.PLAYER_ROLL_COUNT,0)
_setPlayerProp(game, p, PLAYER_PROPS.MISSED_SAFE_ZONES,0)
gameLogic.initPlayerShuffleRoller(game,p);
_setPLayerInitGameScore(game,p);
users.push(game.getUserIdByPlayerId(p))
game.setPlayerRemainingExtraTime(p,isTournament ? 0 : meta.extraTime)
if (p === game.getPlayerSeating()[0]) {
let newRoll = gameLogic.rollADie(game, p);
_setPlayerProp(game, p, PLAYER_PROPS.DIE_ROLL, newRoll);
gameLogic.enablePawns(game, p);
gameLogic.sendTurnInitHHEvent(game,p,newRoll)
} else {
_setPlayerProp(game, p, PLAYER_PROPS.DIE_ROLL, null);
}
let objIds = game.getAllObjIds();
for (let objId of objIds) {
let obj = _gameObjById(game, objId);
if (shuffledColors[i] === obj.type)
game.changeOwner(p, objId);
}
i++;
for( let p1 of game.getPlayerSeating()) {
// mapping - Key[PlayerId_killCount] : Value[opponentKilledCount (# of time opponentPlayer has been killed by player)]
// (initially : 0), p1 - PlayerId, p - OpponentId
if(p!==p1) {
const key = `${p1.toString()}_killCount`;
game.setPlayerProp(p,key,0);
}
}
}
game.publishHHGameEvent(1,"players_initialized", {
assigned_colors : shuffledColors,
turn_wise_player_id : users,
update_time : Date.now()
}
)
_publishGameDiceRollsInfo(game);
}
const onRestoreFromSavepoint = function(game, _) {
const gameKey = game.getId();
const meta = _getMeta(game);
let duration = meta.turnDuration;
let turnExpiry = Date.now() + duration;
logger.info({key: gameKey}, 'Setting turn expiry as', turnExpiry,
'current time is ', Date.now());
game.setGameProp('turnExpiry', turnExpiry);
initRevPosMap(game);
_setGameProp(game, GAME_PROPS.NEXT_TURN_TS, null);
};
const onServerRestart = function(game) {
const gameKey = game.getId();
if (game.getState() >= 30)
return logger.debug({key: gameKey}, 'Game has ended, nothing to do');
game.restoreFromSavepoint('__turn_start', (err, res) => {
if (err)
return logger.error({key: gameKey},
'Error reverting to prev savepoint, post server restart',
'continuing game without restore', err);
logger.info({key: gameKey},
'Successfully reverted to previous state, post server restart');
});
};
const kickTimeHackers = function(game, playerId) {
// logger.info({key: game.getId()}, 'auto forfeiting player', playerId,
// 'due to time hack detection');
// game.forfeitGameForPlayer(playerId, enums.TIME_HACK_DETECTION);
};
function onForfeitForPlayer(game, playerId) {
const gk = {key: game.getId()};
let forfeitEventObj = new eventObjs.forfeit()
logger.info(gk, 'forfeit for player ', playerId);
game.publishGameEvent(1607, [playerId]);
const meta = _getMeta(game);
let isHighestScore = _isHighestScore(game,playerId)
forfeitEventObj.kingdom = _getPlayerProp(game, playerId, PLAYER_PROPS.MISS_MOVES)
forfeitEventObj.score = game.getPlayerScore(playerId)
forfeitEventObj.genus = isHighestScore
game.publishNewGameEvent(playerId, forfeitEventObj)
game.publishHHGameEvent(playerId,"player_forfeit",{
turn_id : game.getCurrentTurnId(),
update_time : Date.now()
})
const currentPlayerId = game.getCurrentTurnPlayerId()
if (playerId !== currentPlayerId) {
_setGameProp(game,GAME_PROPS.ABSOLUTE_WIN_TYPE,0)
if(isHighestScore) triggerForfeitHighScoreEvent(game,playerId)
const isTurnCompleted = _getGameProp(game, GAME_PROPS.IS_TURN_COMPLETED);
const nextTurnPlayerId = game.fetchNextTurnPlayerId()
if(isTurnCompleted && nextTurnPlayerId !== playerId){
gameLogic.turnInit(game,nextTurnPlayerId, false);
}
game.syncGameStateServVars();
return;
}
let curMissMoves = _getPlayerProp(game, playerId, PLAYER_PROPS.MISS_MOVES)
if (curMissMoves < meta.maxMissMoves) {
_setGameProp(game,GAME_PROPS.ABSOLUTE_WIN_TYPE,0)
if(isHighestScore) triggerForfeitHighScoreEvent(game,playerId)
}
logger.debug(gk, 'forfeit player is current player', playerId);
gameLogic.destroyForfeitPlayerPawns(game).catch(e => {
logger.error(gk, 'forfeit player failed with exception', e);
});
gameLogic.turnEndHandler(game, playerId);
}
const triggerForfeitHighScoreEvent = function (game,playerId){
const gk = {key: game.getId()};
let isForfeitTurnCountBreached = _isForfeitTurnCountBreached(game,playerId)
if(isForfeitTurnCountBreached) {
_setGameProp(game,GAME_PROPS.FORFEIT_HIGHEST_PLAYER_SCORE,game.getPlayerScore(playerId))
_setGameProp(game,GAME_PROPS.FORFEIT_HIGHEST_PLAYER_ID,playerId)
_setGameProp(game,GAME_PROPS.IS_FORFEIT_FRAUD_BY_ANY_PLAYER,true)
logger.debug(gk, 'forfeit turn count threshold breached player is current player', playerId,
isForfeitTurnCountBreached);
let fraudForfeitEvent = new eventObjs.fraudForfeit()
game.publishGameFraudEvent(playerId,fraudForfeitEvent)
}
}
const playerConnected = function(game, playerId) {
const gk = {key: game.getId()};
let currentPlayerId = game.getCurrentTurnPlayerId();
let timeLeft = _getGameTimeLeft(game,currentPlayerId)
if (isNaN(timeLeft.gameTime)) return;
_setGameProp(game, GAME_PROPS.GAME_TIMER_REMAINING,
timeLeft.gameTime >= 0 ? timeLeft.gameTime : 0);
logger.debug(gk,"time left while player connected,", timeLeft)
if(timeLeft.isExtraTimeEnabled && timeLeft.extraTime) {
game.setPlayerRemainingExtraTime(currentPlayerId, timeLeft.extraTime)
_setGameProp(game, enums.GAME_PROPS.EXTRA_TIME_CHECK_TIME, Date.now());
}
return true;
};
const handleGameOptions = function(game, gameOptions) {
if (!(typeof gameOptions === 'object') || !gameOptions.prizeDist) {
return;
}
_setGameProp(game, 'prizeDist', JSON.stringify(gameOptions.prizeDist));
};
module.exports = {
startGame,
onRestoreFromSavepoint,
onServerRestart,
kickTimeHackers,
mapToLoad,
onForfeitForPlayer,
gameStarted,
playerConnected,
handleGameOptions,
};