Merge branch 'feature/serverSide' into develop

develop
Nathan Steel 1 year ago
commit 579848c84c

@ -4,22 +4,12 @@ const database = require('./database');
const util = require('util') const util = require('util')
// cardClass, cardColourRequirement // Get the decks requested
// may want to be seperate too (as well as in cardItem), so that
// during match they can be altered by effects while keeping the OG card
// for inspecting (and compare against new stats,reqs,etc.)
// same with attack, cost, etc. things that will can be visually shown as
// changed in game
// Just grabbing everything from DB for now, as it's quite small at current
// then will rejig when needed.
// Should all cards, effects, classes etc. be loaded in on server start
// then just load decks and decklists when needed?
function getDecks(deckIds = false){ function getDecks(deckIds = false){
// Await promise, once it's done get the data, if errors send err // Await promise, once it's done get the data, if errors send err
const dPromise = new Promise((resolve, reject) => { const dPromise = new Promise((resolve, reject) => {
database.dbGetDecks().then(data => { database.dbGetDecks(deckIds).then(data => {
let decks = []; let decks = [];
@ -48,10 +38,10 @@ function getDecks(deckIds = false){
return dPromise; return dPromise;
} }
//getDecks(); //getDecks();
function getDeckList(){ function getDeckList(deckIds = false){
const dPromise = new Promise((resolve, reject) => { const dPromise = new Promise((resolve, reject) => {
database.dbGetDeckList().then(data => { database.dbGetDeckList(deckIds).then(data => {
let deckList = []; let deckList = [];
@ -70,11 +60,10 @@ function getDeckList(){
}); });
return dPromise; return dPromise;
} }
//getDeckList(); function getCards(cardIds = false){
function getCards(){
const dPromise = new Promise((resolve, reject) => { const dPromise = new Promise((resolve, reject) => {
database.dbGetCards().then(data => { database.dbGetCards(cardIds).then(data => {
let cards = []; let cards = [];
@ -97,10 +86,9 @@ function getCards(){
}); });
return dPromise; return dPromise;
} }
//getCards(); function getCardClasses(cardIds = false){
function getCardClasses(){
const dPromise = new Promise((resolve, reject) => { const dPromise = new Promise((resolve, reject) => {
database.dbGetCardClasses().then(data => { database.dbGetCardClasses(cardIds).then(data => {
let cardClasses = []; let cardClasses = [];
@ -118,10 +106,9 @@ function getCardClasses(){
}); });
return dPromise; return dPromise;
} }
//getCardClasses(); function getCardColourRequirement(cardIds = false){
function getCardColourRequirement(){
const dPromise = new Promise((resolve, reject) => { const dPromise = new Promise((resolve, reject) => {
database.dbGetCardColourRequirement().then(data => { database.dbGetCardColourRequirement(cardIds).then(data => {
let colourRequirements = []; let colourRequirements = [];
@ -141,9 +128,9 @@ function getCardColourRequirement(){
}); });
return dPromise; return dPromise;
} }
function getCardManaColour(){ function getCardManaColour(cardIds = false){
const cPromise = new Promise((resolve, reject) => { const cPromise = new Promise((resolve, reject) => {
database.dbGetCardManaColour().then(data => { database.dbGetCardManaColour(cardIds).then(data => {
let manaColours = []; let manaColours = [];
@ -274,25 +261,9 @@ function getCardPassive(){
return cPromise; return cPromise;
} }
//getCardColourRequirement();
// Then effects which will have effects with parent triggers, and unit type checks
// colour checks, all sorts. So will be more difficult. Basic (flight, etc)
// shouldn't be too bad
// something like effect_basic, card_effect, effect_trigger, effect_requirement, effect_option
// effect_stage, effect_advanced, with advanced being an id with x triggers, triggers have
// x req, advanced as with x options, x stages to be able to fine-tune fancy stuff
// combining all other effects, units, cards, colours, etc. Will be a lot of though,
// but better than hard coding anything more than basic effects and effect check logic
// TODO: effect (as above)
// request a deck in the format CURRENTLY used in the game
// decks will likely be changed around
// https://www.geeksforgeeks.org/how-to-wait-for-multiple-promises-in-javascript/ // https://www.geeksforgeeks.org/how-to-wait-for-multiple-promises-in-javascript/
// https://medium.com/@nikolozz/using-socket-io-with-async-await-13fa8c2dc9d9 // https://medium.com/@nikolozz/using-socket-io-with-async-await-13fa8c2dc9d9
// using last example
// TODO: When this is functionally working, need to split up into other func/modules
// such as: playerMod, cardMod, deckMod, miscMod ?
function requestDeck(itemData = null){ function requestDeck(itemData = null){
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
(async () => { (async () => {
@ -300,53 +271,73 @@ function requestDeck(itemData = null){
// Get the deck(s) requested. // Get the deck(s) requested.
// Not 100% on how to do two differening atm // Not 100% on how to do two differening atm
// Besides all of playerId, and all of deckId. But 1,2/2,3 for instance // Besides all of playerId, and all of deckId. But 1,2/2,3 for instance
// Build array of decks to get
let deckIds = [];
for(let i = 0; i < itemData.players.length; i++){
let deckStuff = itemData.players[i][1].deck;
deckIds.push([deckStuff.playerId, deckStuff.deckId]);
// So should be array of [playerId, deckId] which is primary key in DB
}
// Get said decks, and their deckLists
const [decks, deckList] = const [decks, deckList] =
await Promise.all([ await Promise.all([
getDecks(), getDecks(deckIds),
getDeckList() getDeckList(deckIds)
]); ]);
//console.log(decks); /*
//console.log(deckList); console.log('--- decks ---');
console.log(decks);
console.log('= deckLists =')
console.log(deckList);
console.log('------');
*/
// Now loop the deckList for the cardIds // Now loop the deckList for the cardIds
let deckCardIds = []; let deckCardIds = [];
deckList.forEach((deckItem) => { deckList.forEach((deckItem) => {
deckCardIds.push(deckItem.cardId); deckCardIds.push(deckItem.cardId);
}); });
//console.log(deckCardIds);
// Next, get the cards in the deck by their ID // Next, get the cards in the deck by their ID
// TODO: https://stackoverflow.com/a/65510676 // TODO: https://stackoverflow.com/a/65510676
// Change SQL to accept for just the cards passed
// Get each cards data, colourReqs, and classes // Get each cards data, colourReqs, and classes
const [cards, cardClasses, cardColourRequirements, cardManaColours, cardPassives] = const [cards, cardClasses, cardColourRequirements, cardManaColours, cardPassives] =
await Promise.all([ await Promise.all([
getCards(), getCards(deckCardIds),
getCardClasses(), getCardClasses(deckCardIds),
getCardColourRequirement(), getCardColourRequirement(deckCardIds),
getCardManaColour(), getCardManaColour(deckCardIds),
getCardPassive(), getCardPassive(deckCardIds),
]); ]);
// ^^^^ Classes async? Can pass the cardsIds, then loop classes, if the class cardId // Return all effect data from DB
// matches the cardId in cards[] then push the class to cards[x].classes const [effects] =
await Promise.all([
database.dbGetEffect(deckCardIds), // Get effects
]);
// TODO: Build the card so far async for it's done alongside getting effects? // Loop the effects for their effectIds to then get the steps/triggers from DB
// Then when both done add the effects to the existing cardObjects? Yep good idea me let effectIds = [];
//console.log(cards); await effects.forEach((effect) => {
//console.info(cardClasses); effectIds.push(effect.effectId);
//console.log(cardColourRequirements); });
// Return all effect data from DB // Then pass the effectIds to get their steps/triggers
const [effects, effectSteps, effectTriggers] = const [effectSteps, effectTriggers] =
await Promise.all([ await Promise.all([
database.dbGetEffect(), database.dbGetEffectStep(effectIds),
database.dbGetEffectStep(), database.dbGetEffectTrigger(effectIds),
database.dbGetEffectTrigger(),
]); ]);
/*
console.log('--- Effects ---');
console.log(effects);
*/
// Build Effects // Build Effects
const [cardEffects] = const [cardEffects] =
await Promise.all([ await Promise.all([
@ -460,6 +451,8 @@ function requestDeck(itemData = null){
// For each new card, loop to the cardCount (how many cards in deck) // For each new card, loop to the cardCount (how many cards in deck)
// and add to the deck // and add to the deck
// TODO: Associate player to deck differently (both could be using same deck
// via some kind of 'try a deck' or 'use friends deck' option)
for(let i = 0; i < deckListItem.cardCount; i++){ for(let i = 0; i < deckListItem.cardCount; i++){
item.push(itemCount); // Add new item to add stuff for item.push(itemCount); // Add new item to add stuff for
// ^ not using item.length incase anything in future gets deleted // ^ not using item.length incase anything in future gets deleted

@ -0,0 +1,99 @@
// A seperate list for components, so they're easy to recall
// Done as object, so it can be added to different rooms with components = NEW component?
const component = {
// Entity Stuff
//item : [],
//itemCount : 0,
roomId : null,
turn : 0,
playerTurn : 0,
// Card Stuff
cardData : {},
cardFace : {},
cardStatus : {
tapped : {},
attacking : {},
inspected : {},
},
cardAttack : {},
cardColours : {}, // Replace with colour
colour : {
white : {}, // entityId, amountOfColour
blue : {},
red : {},
},
cardManaColour : {},
cardEffect : {}, // TODO: Split this into effect, trigger, step, targets.
cardCost : {},
cardSprite : {}, // id, position in spritesheet [0,4] e.g.
//cardPlayer = {},
// Deck Stuff?
deckIn : {},
deckData : {},
// UI (so users know what's been targetted)
selected : {},
selectable : {},
// Effect (break it up?)
effect : {},
effectTrigger : {},
// etc, etc.
// Board Elements
// loop component.shield for shield items
boardElement : {},
// Replace with following
realDeck : {},
inDeck : {},
hand : {},
board : {},
shield : {},
mana : {},
grave : {},
void : {},
//
listPosition : {},
// position (clientside)
// size (clientside)
// Passives
// component.passive.flight ?
passive : {
flight : {},
reach : {},
taunt : {},
},
type : {
unit : {},
spell : {},
token : {},
},
classes : {
orc : {},
human : {},
spirit : {},
},
};
// For front-end
// position, size
// These should be used as such (Not 100% as yet)
// For onBoard()... for player()... for passive.flight()...
// Check the board, items belonging to playerX, for flight passive?
module.exports = {
component
}

@ -17,7 +17,7 @@ function disconnect(){
} }
// My DB stuffs // My DB stuffs
function dbGetDecks(){ function dbGetDecks(deckIds = false){
const dPromise = new Promise((resolve, reject) => { const dPromise = new Promise((resolve, reject) => {
let cards = []; let cards = [];
let sql = `SELECT let sql = `SELECT
@ -25,8 +25,16 @@ function dbGetDecks(){
,playerId ,playerId
,deckName ,deckName
FROM deck FROM deck
LIMIT 10 `;
`; // TODO: Remove limit when happy/this accepts params
// TODO: Jank, need to unjank it
if(deckIds){
for(let i = 0; i < deckIds.length; i++){
if(i == 0){ sql += ' WHERE '; }
else{ sql += ' OR '; }
sql += '(deckId = '+deckIds[i][1]+' AND playerId = '+deckIds[i][0]+')';
}
}
con.query(sql, function (err, result, fields) { con.query(sql, function (err, result, fields) {
if (err) { throw err; reject(new Error(err)); } if (err) { throw err; reject(new Error(err)); }
@ -35,7 +43,7 @@ function dbGetDecks(){
}); });
return dPromise; return dPromise;
} }
function dbGetDeckList(){ function dbGetDeckList(deckIds = false){
const dPromise = new Promise((resolve, reject) => { const dPromise = new Promise((resolve, reject) => {
let cards = []; let cards = [];
let sql = `SELECT let sql = `SELECT
@ -46,6 +54,15 @@ function dbGetDeckList(){
FROM deck_cards FROM deck_cards
`; `;
// TODO: Jank, need to unjank it
if(deckIds){
for(let i = 0; i < deckIds.length; i++){
if(i == 0){ sql += ' WHERE '; }
else{ sql += ' OR '; }
sql += '(deckId = '+deckIds[i][1]+' AND playerId = '+deckIds[i][0]+')';
}
}
con.query(sql, function (err, result, fields) { con.query(sql, function (err, result, fields) {
if (err) { throw err; reject(new Error(err)); } if (err) { throw err; reject(new Error(err)); }
resolve(result); resolve(result);
@ -53,7 +70,7 @@ function dbGetDeckList(){
}); });
return dPromise; return dPromise;
} }
function dbGetCards(){ function dbGetCards(cardIds = false){
// Start with basic stuff in card table // Start with basic stuff in card table
const dPromise = new Promise((resolve, reject) => { const dPromise = new Promise((resolve, reject) => {
let sql = `SELECT let sql = `SELECT
@ -65,6 +82,7 @@ function dbGetCards(){
,cardRarity ,cardRarity
FROM card FROM card
`; `;
if(cardIds){ sql += 'WHERE card.id IN ('+cardIds+')'; }
con.query(sql, function (err, result, fields) { con.query(sql, function (err, result, fields) {
if (err) { throw err; reject(new Error(err)); } if (err) { throw err; reject(new Error(err)); }
@ -73,7 +91,7 @@ function dbGetCards(){
}); });
return dPromise; return dPromise;
} }
function dbGetCardClasses(){ function dbGetCardClasses(cardIds = false){
// Get the classes assoc. on each card // Get the classes assoc. on each card
const dPromise = new Promise((resolve, reject) => { const dPromise = new Promise((resolve, reject) => {
let sql = `SELECT let sql = `SELECT
@ -81,6 +99,7 @@ function dbGetCardClasses(){
,classId ,classId
FROM card_class FROM card_class
`; `;
if(cardIds){ sql += 'WHERE cardId IN ('+cardIds+')'; }
con.query(sql, function (err, result, fields) { con.query(sql, function (err, result, fields) {
if (err) { throw err; reject(new Error(err)); } if (err) { throw err; reject(new Error(err)); }
@ -89,7 +108,7 @@ function dbGetCardClasses(){
}); });
return dPromise; return dPromise;
} }
function dbGetCardColourRequirement(){ function dbGetCardColourRequirement(cardIds = false){
// Get the classes assoc. on each card // Get the classes assoc. on each card
const dPromise = new Promise((resolve, reject) => { const dPromise = new Promise((resolve, reject) => {
let sql = `SELECT let sql = `SELECT
@ -98,6 +117,7 @@ function dbGetCardColourRequirement(){
,cost ,cost
FROM card_colour_requirement FROM card_colour_requirement
`; `;
if(cardIds){ sql += 'WHERE cardId IN ('+cardIds+')'; }
con.query(sql, function (err, result, fields) { con.query(sql, function (err, result, fields) {
if (err) { throw err; reject(new Error(err)); } if (err) { throw err; reject(new Error(err)); }
@ -107,7 +127,7 @@ function dbGetCardColourRequirement(){
return dPromise; return dPromise;
} }
function dbGetCardManaColour(){ function dbGetCardManaColour(cardIds = false){
// Get the classes assoc. on each card // Get the classes assoc. on each card
const cPromise = new Promise((resolve, reject) => { const cPromise = new Promise((resolve, reject) => {
let sql = `SELECT let sql = `SELECT
@ -115,6 +135,7 @@ function dbGetCardManaColour(){
,colourId ,colourId
FROM card_mana_colour FROM card_mana_colour
`; `;
if(cardIds){ sql += 'WHERE cardId IN ('+cardIds+')'; }
con.query(sql, function (err, result, fields) { con.query(sql, function (err, result, fields) {
if (err) { throw err; reject(new Error(err)); } if (err) { throw err; reject(new Error(err)); }
@ -125,7 +146,7 @@ function dbGetCardManaColour(){
} }
// Effect stuff // Effect stuff
function dbGetEffect(){ function dbGetEffect(cardIds = false){
const ePromise = new Promise((resolve, reject) => { const ePromise = new Promise((resolve, reject) => {
let sql = `SELECT let sql = `SELECT
cardId cardId
@ -136,6 +157,7 @@ function dbGetEffect(){
INNER JOIN effect INNER JOIN effect
ON effect.id = card_effect.effectId ON effect.id = card_effect.effectId
`; `;
if(cardIds){ sql += 'WHERE cardId IN ('+cardIds+')'; }
con.query(sql, function (err, result, fields) { con.query(sql, function (err, result, fields) {
if (err) { throw err; reject(new Error(err)); } if (err) { throw err; reject(new Error(err)); }
@ -144,7 +166,7 @@ function dbGetEffect(){
}); });
return ePromise; return ePromise;
} }
function dbGetEffectStep(){ function dbGetEffectStep(effectIds = false){
const ePromise = new Promise((resolve, reject) => { const ePromise = new Promise((resolve, reject) => {
let sql = `SELECT let sql = `SELECT
effectId, effectId,
@ -163,6 +185,7 @@ function dbGetEffectStep(){
effect_step_target effect_step_target
ON effect_step_target.effectStep = effect_step.id ON effect_step_target.effectStep = effect_step.id
`; `;
if(effectIds){ sql += 'WHERE effectId IN ('+effectIds+')'; }
con.query(sql, function (err, result, fields) { con.query(sql, function (err, result, fields) {
if (err) { throw err; reject(new Error(err)); } if (err) { throw err; reject(new Error(err)); }
@ -172,7 +195,7 @@ function dbGetEffectStep(){
return ePromise; return ePromise;
} }
// Effect Trigger stuff // Effect Trigger stuff
function dbGetEffectTrigger(){ function dbGetEffectTrigger(effectIds = false){
const ePromise = new Promise((resolve, reject) => { const ePromise = new Promise((resolve, reject) => {
let sql = `SELECT let sql = `SELECT
effect_trigger.id AS triggerId, effect_trigger.id AS triggerId,
@ -196,6 +219,7 @@ function dbGetEffectTrigger(){
effect_trigger_target effect_trigger_target
ON effect_trigger_target.effectTriggerId = effect_trigger.triggerTypeId ON effect_trigger_target.effectTriggerId = effect_trigger.triggerTypeId
`; `;
if(effectIds){ sql += 'WHERE effectId IN ('+effectIds+')'; }
con.query(sql, function (err, result, fields) { con.query(sql, function (err, result, fields) {
if (err) { throw err; reject(new Error(err)); } if (err) { throw err; reject(new Error(err)); }
@ -206,13 +230,14 @@ function dbGetEffectTrigger(){
} }
// Passive stuff // Passive stuff
function dbGetPassive(){ function dbGetPassive(cardIds = false){
const pPromise = new Promise((resolve, reject) => { const pPromise = new Promise((resolve, reject) => {
let sql = `SELECT let sql = `SELECT
cardId cardId
,passiveId ,passiveId
FROM card_passive FROM card_passive
`; `;
if(cardIds){ sql += 'WHERE card.id IN ('+cardIds+')'; }
con.query(sql, function (err, result, fields) { con.query(sql, function (err, result, fields) {
if (err) { throw err; reject(new Error(err)); } if (err) { throw err; reject(new Error(err)); }

@ -0,0 +1,25 @@
// For anything related to the actual game itself (kinda)
// this will be split into different bits, but should be what manages a rooms
// game states, and alladat
// Basically here to prevent circular dependencies (where I can)
// PlayerId is using array 0,1,2 for now, not the actual id
// actual Id would be better, but the player should be passed correctly
// from the client. They can edit data, but server-side validation SHOULD prevent
// in the future
function passTurn(roomId, playerId){
// Check playerId (not correct atm) before doing the stuff, to verify the user
// IS the user, and in the room
// Test alert so that different data/emits can be sent per-player
global.socketAlert(roomData[roomId].playerData[0].socketId, 'Pass', 'alert');
}
module.exports = {
passTurn
};

@ -42,6 +42,7 @@ let cardColours = {};
let cardManaColour = {}; let cardManaColour = {};
let cardEffect = {}; let cardEffect = {};
let inEvent = null; let inEvent = null;
let roomId = null;
// To disable drawing each time something changes // To disable drawing each time something changes
let drawEachEvent = true; // For disabling draw each time and only occuring where I want to test let drawEachEvent = true; // For disabling draw each time and only occuring where I want to test
@ -1298,6 +1299,7 @@ function loadBoard(data) {
cardColours = data.cardColours; cardColours = data.cardColours;
cardManaColour = data.cardManaColour; cardManaColour = data.cardManaColour;
cardEffect = data.cardEffect; cardEffect = data.cardEffect;
roomId = data.roomId;
// Passives // Passives
flight = data.flight; flight = data.flight;

@ -17,6 +17,10 @@
</div> </div>
<canvas id="canvas" width="1000" height="600"></canvas> <canvas id="canvas" width="1000" height="600"></canvas>
<hr>
<button onclick="passTurn()">Pass Turn</button>
<br><br>
<hr> <hr>
<button onclick="untapAllZones()">Untap all</button> <button onclick="untapAllZones()">Untap all</button>
<button onclick="echoCards()">Print cardlist to console</button> <button onclick="echoCards()">Print cardlist to console</button>

@ -182,3 +182,19 @@ socket.on('responseStartGame', function (data) {
loadBoard(data.message); loadBoard(data.message);
}); });
// ALERTS
socket.on('alert', function (data) {
console.log('<< alert');
alert(data.message);
});
// GAME SERVER STUFF
// PASS TURN
function passTurn(){
// TODO: Use itemData.player/itemData.room or whatnot here
console.log(roomId);
let playerId = prompt('PlayerId 0/1', 0); // TODO: very temp, will be playerId/arrayId
console.log('+ passTurn');
socket.emit('passTurn', roomId, playerId);
}

@ -1,41 +1,34 @@
// Build a room, fill will players, etc. // Build a room, fill will players, etc.
const cardGen = require('./cardGen'); const cardGen = require('./cardGen');
const components = require('./components');
// Room should, setPlayers, add them to correct team (TODO), build their decks, and first shuffle // Room should, setPlayers, add them to correct team (TODO), build their decks, and first shuffle
function startItemCount(){ function startItemCount(){
let item = []; let item = [];
let itemCount = 0; let itemCount = 0;
returns = {'item': item, 'itemCount': itemCount}; returns = {'item': item, 'itemCount': itemCount};
return(returns); return(returns);
} }
function setPlayers(playerCount = 2, itemData){
// Add new item attribute for 'players' function setPlayers(playerData, itemData){
// TODO: Maybe check if exists, and add to in that case (for replacing people?)
// Doubt that would ever make it into the game, but could still be worth
itemData.player = {}; //let player = {}; // Player item belongs to itemData.player = {}; //let player = {}; // Player item belongs to
itemData.players = []; // List of the players (an associated playerItem?) itemData.players = []; // List of the players (an associated playerItem?)
//itemData.
// Can be done with just referring to itemData[x], but less readable
// Will likely redefine vars each new function. For now will keep this as-is
let playerNo = 0 + itemData['itemCount']; // Start loop from current itemCount let playerNo = 0 + itemData['itemCount']; // Start loop from current itemCount
playerCount = playerCount + itemData['itemCount']; // End at playerCount diff from itemCount playerCount = playerData.length + itemData['itemCount']; // End at playerCount diff from itemCount
let i = 0;
for(playerNo; playerNo < playerCount; playerNo++){ for(playerNo; playerNo < playerCount; playerNo++){
// REMOVED PLAYERS AS ITEM, BECAUSE THEY WERE BORKING
// TODO: Add back at some point, or don't bother itemData['players'].push([playerNo, playerData[i]]); // Add player no to array so can be looped
//itemData['item'].push(playerNo); i++;
//itemData['player'][itemData['itemCount']] = playerNo; // The player belongs to itself
//itemData['itemCount']++;
itemData['players'].push(playerNo); // Add player no to array so can be looped
} }
// Return related item and item attributes
//returns = {'item': item, 'itemCount': itemCount, 'player': player};
return itemData; return itemData;
//return([item, itemCount, player]);
} }
// For future, when 2v2s, and 5v1 Raids, etc. // For future, when 2v2s, and 5v1 Raids, etc.
@ -43,26 +36,72 @@ function setTeams(){
} }
function roomGeneration(playerCount, teamCount = null, playerTeams = null){ function roomGeneration(roomId){
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
(async () => { (async () => {
// Player's sockets
console.log('--- Room for generation ---');
console.log(io.sockets.adapter.rooms.get(roomId));
let itemData = startItemCount(); let itemData = startItemCount();
// Create 2 players for the room // Player data with Sockets
itemData = setPlayers(2, itemData); let playerData = [];
let playerOrder = {}; // Need a better name
let i = 1;
let clients = global.io.sockets.adapter.rooms.get(roomId);
for (const clientId of clients) {
const clientSocket = global.io.sockets.sockets.get(clientId);
// TODO: Get their selected decks (will need to pass somewhere) // Which order the player is? Just using the array
playerOrder[clientSocket.playerId] = playerData.length;
playerData.push({
'playerDataId': playerData.length
,'playerId': clientSocket.playerId
,'deck':{'playerId':i,'deckId':1}
,'socketId': clientSocket.id // TODO: ONLY FOR SERVERSIDE!!!
});
i++;
}
// Add players for the room (seperate to playerData, currently what's used)
// ??
itemData = setPlayers(playerData, itemData);
// TODO: Get their selected decks
// Add all the empty components to the room itemData
itemData.component = components.component;
// Generate the decks, and card within the deck cardLists // Generate the decks, and card within the deck cardLists
[itemData] = await Promise.all([ cardGen.requestDeck(itemData) ]); [itemData] = await Promise.all([ cardGen.requestDeck(itemData) ]);
//console.log('deckData'); // Some room stuff, likely change this
//console.log(deckData); itemData.roomId = roomId;
itemData.turn = 0; // The turn count of the match
itemData.playersTurn = 0; // This means it's playerData[0] turn
// Room has just been created, so add the itemData and playerData to the room
// on server-side so it's easily accessible
roomData[roomId].itemData = itemData;
roomData[roomId].playerData = playerData;
roomData[roomId].playerOrder = playerOrder;
// Return the all the itemData to the client(s)
// TODO: This will need to give different data for each, or at least
// to differ the boardside
return resolve(itemData); return resolve(itemData);
})() })()
}); });
} }
// TODO: disconnect, reconnect, resume
module.exports = { module.exports = {
startItemCount startItemCount
,setPlayers ,setPlayers

@ -0,0 +1,229 @@
const roomMod = require('./roomMod');
// Variables for server overall
let numRooms = 0;
const maxRooms = 3;
const maxPlayersPerRoom = 2;
const maxSpectatorsPerRoom = 0;
function requestRooms(socket, filter){
console.log('+ requestRooms recieved');
console.log('- filter: '+filter);
let response = getRooms(filter, dump = true);
global.io.to(socket.id).emit('returnRooms', response);
console.log('');
}
function getRooms(filter = 'all', dump = false){
console.log('+ getRooms');
let response = {
random: 'randomStuff',
roomData: global.roomData,
};
if(dump){
console.log(response);
console.log('');
}
return response;
}
function requestCreateRoom(socket, playerName){
console.log('+ createRoom recieved');
console.log('- requested by: '+playerName);
response = createRoom(roomId = false, dump = true);
global.io.to(socket.id).emit('returnCreateRoom', response);
if(response.success){
let response = getRooms(filter = 'all', dump = true);
global.io.to(socket.id).emit('returnRooms', response);
}
console.log('');
}
function createRoom(roomId = false, dump = true){
let roomName = false;
if(roomId == false){
roomId = numRooms + 1;
}
console.log(roomId);
let response = {
success: false,
message: 'No idea bossman'
};
// Max room limit reached
console.log(numRooms);
console.log(maxRooms);
if(numRooms >= maxRooms){
console.log('- Room limit reached');
response = {
success: false,
message: 'No space '+numRooms+' out of '+maxRooms+' created.'
};
// Create room
}else{
console.log('- Creating room')
let room = {};
room['id'] = roomId;
room['name'] = 'Room:'+room['id'];
roomName = room['name'];
room['password'] = '';
room['timeout'] = {};
room['timeout']['s'] = 10;
room['people'] = 0;
room['playerIds'] = {};
global.roomData[roomId] = room;
numRooms = numRooms + 1;
response = {
success: true,
message: 'Room Created: '+roomName,
};
}
if(dump){
console.log(response);
console.log('');
}
return response;
}
function requestJoinRoom(socket, playerName, roomId){
console.log('+ requestJoinRoom recieved');
let room = global.roomData[roomId];
// https://stackoverflow.com/a/18096649
socket.playerId = playerName;
if(room === undefined){
console.log('>> Room does not exist');
return 'error';
}
let roomName = 'Room_' + roomId;
let people = room['people'];
if(isUserInRoom(playerName, roomId)){
console.log('>> Already in room');
return 'already in room';
}
if (people < maxPlayersPerRoom) {
// Update people in room count
people = room['people'] += 1;
// Add playerId to room (playerName for now while Ids don't exist TODO)
room['playerIds'][playerName] = playerName;
// https://socket.io/docs/v4/rooms/
// https://stackoverflow.com/a/25028953
socket.join(roomId);
console.log('>> User ' + playerName +
' connected on ' + roomName + ' (' + (people) + '/' + maxPlayersPerRoom + ')');
// Joined room (emit to the player that just joined)
global.io.to(socket.id).emit('responseRoom', response);
if (people >= maxPlayersPerRoom) {
console.log('- starting game');
// startGame for room
startGame(roomId);
}
}
}
// Will need to be different to playerName in future (in case dupes)
// would use playerId TODO
function isUserInRoom(playerName, roomId){
if(playerName in global.roomData[roomId]['playerIds']){
return true;
}
return false;
}
async function startGame(roomId){
console.log('>> Room: ' + roomId + ': Requesting game...');
let people = global.roomData[roomId].players;
/*
try {
//people = io.sockets.adapter.rooms.get(roomId).size;
} catch (e) {
console.log('>> Room: ' + roomId + ': No people here...');
return;
}
*/
// For now, if there's 2 people only. Will need changing for
// 3v1, 5v1, 2v2, etc...
let response = {success: false, message: 'Failed requestStartGame() server.js'};
if(people < maxPlayersPerRoom){
console.log('Too few people');
}
console.log('>> Room: ' + roomId + ': Starting');
// https://stackoverflow.com/a/25028953
//console.log(util.inspect(io.sockets.adapter.rooms.get(roomId), true, 4, true))
let clients = global.io.sockets.adapter.rooms.get(roomId);
// This should return the deck data, etc. for each client
// ideally only returning the items that the user can/should
// see i.e. shouldn't give them the inDeck card list just a counter
// shouldn't have opponent card data/their hand shouldn't be flipped
// Not sure how to catch errors for these await alls
// TODO: Look into error handling for await alls
const [itemData] =
await Promise.all([
roomMod.roomGeneration(roomId),
]);
// data is the 'itemData' not all the roomData
response.success = true;
response.message = itemData;
// Each player then gets sent the roomGeneration stuff
for (const clientId of clients) {
const clientSocket = global.io.sockets.sockets.get(clientId);
console.log('>> responseStartGame: '+clientSocket.playerId);
// TODO: TESTING STUFF, REMOVE WHEN SORTED
let message = 'You are player: '+roomData[roomId].playerOrder[clientSocket.playerId];
global.socketAlert(clientSocket.id, message, 'alert');
// Emit the itemData to client socket (TODO: only emit what each player should see/recieve)
global.io.to(clientSocket.id).emit('responseStartGame', response);
}
}
// TODO: Need a 'leave room'/disconnect
module.exports = {
requestRooms
,requestJoinRoom
,requestCreateRoom
};

@ -1,13 +1,21 @@
const express = require('express'); const express = require('express');
const database = require('./database'); const database = require('./database');
const cardGen = require('./cardGen'); const rooms = require('./rooms');
const roomMod = require('./roomMod'); const gameMod = require('./gameMod');
const app = express(); const app = express();
const http = require('http').Server(app); const http = require('http').Server(app);
const port = process.env.PORT || 3000; const port = process.env.PORT || 3000;
const io = require('socket.io')(http); const io = require('socket.io')(http);
global.io = io;
// To log the player sockets, so they can be easily referred to
// maybe jank, but can't see alternative currently
global.playerSocket = {};
global.roomData = {}; // Made global for now, as to not replicate. Maybe sub-optimal?
// util is what nodejs uses for console.log, but has a depth of 2 set // util is what nodejs uses for console.log, but has a depth of 2 set
// so console.logs show [Array]/[Object] instead of useful info. // so console.logs show [Array]/[Object] instead of useful info.
// This can be overridden console.log(util.inspect(LOGDATA, true, 4, true)) // This can be overridden console.log(util.inspect(LOGDATA, true, 4, true))
@ -21,309 +29,38 @@ database.connect();
io.on('connection', onConnection); io.on('connection', onConnection);
// Variables
let numRooms = 0;
let numRoomsToPreGen = 1;
const maxRooms = 3;
const maxPlayersPerRoom = 2;
const maxSpectatorsPerRoom = 0;
// All the room
//let data = []; // Normal array
let data = {}; // Object array (this one for returning to player, and JSON stringify while keeping named ids)
let roomData = {};
for (let roomId = 1; roomId <= numRoomsToPreGen; roomId++) {
// Never have more rooms than max rooms!!!
if(numRooms > maxRooms){
break;
}
createRoom(roomId);
}
function onConnection(socket){ function onConnection(socket){
console.log('+ User connected'); console.log('+ User connected');
console.log(''); console.log('');
// Rooms (joining, creating, etc)
socket.on('requestRooms', function(filter) { socket.on('requestRooms', function(filter) {
requestRooms(socket, filter); rooms.requestRooms(socket, filter);
}); });
socket.on('requestJoinRoom', function(playerName, roomId) { socket.on('requestJoinRoom', function(playerName, roomId) {
requestJoinRoom(socket, playerName, roomId); rooms.requestJoinRoom(socket, playerName, roomId);
}); });
socket.on('requestCreateRoom', function(playerName) { socket.on('requestCreateRoom', function(playerName) {
requestCreateRoom(socket, playerName); rooms.requestCreateRoom(socket, playerName);
}); });
} // Game (actual things relating to the game)
// The socket should only be in one game, so socket.on should
function requestRooms(socket, filter){ // do this, but passing room/player anyways as it's how I've written some
console.log('+ requestRooms recieved'); // roomData bits. TODO: Look if I can do this better...
console.log('- filter: '+filter); socket.on('passTurn', function(roomId, playerId) {
gameMod.passTurn(roomId, playerId);
let response = getRooms(filter, dump = true);
io.to(socket.id).emit('returnRooms', response);
console.log('');
}
function getRooms(filter = 'all', dump = false){
console.log('+ getRooms');
let response = {
random: 'randomStuff',
roomData: roomData,
};
if(dump){
console.log(response);
console.log('');
}
return response;
}
function requestCreateRoom(socket, playerName){
console.log('+ createRoom recieved');
console.log('- requested by: '+playerName);
response = createRoom(roomId = false, dump = true);
io.to(socket.id).emit('returnCreateRoom', response);
if(response.success){
let response = getRooms(filter = 'all', dump = true);
io.to(socket.id).emit('returnRooms', response);
}
console.log('');
}
function createRoom(roomId = false, dump = true){
let roomName = false;
if(roomId == false){
roomId = numRooms + 1;
}
console.log(roomId);
let response = {
success: false,
message: 'No idea bossman'
};
// Max room limit reached
console.log(numRooms);
console.log(maxRooms);
if(numRooms >= maxRooms){
console.log('- Room limit reached');
response = {
success: false,
message: 'No space '+numRooms+' out of '+maxRooms+' created.'
};
// Create room
}else{
console.log('- Creating room')
let room = {};
room['id'] = roomId;
room['name'] = 'Room:'+room['id'];
roomName = room['name'];
room['password'] = '';
room['timeout'] = {};
room['timeout']['s'] = 10;
room['people'] = 0;
room['playerIds'] = {};
//room['deck'] = [];
//room['turn'] = 0;
// Removed players for now, players may be seperate
// and back-end only with an assoc. to current room
//let players = {};
//for (let j = 0; j < maxPlayersPerRoom; j++) {
//let p = {};
//p['id'] = 0;
//p['name'] = "";
//p['hand'] = {};
//players[j] = p;
//}
//room['players'] = players;
roomData[roomId] = room;
numRooms = numRooms + 1;
response = {
success: true,
message: 'Room Created: '+roomName,
};
}
if(dump){
console.log(response);
console.log('');
}
return response;
}
// TODO: break into requestJoinRoom, and JoinRoom?
// Maybe not needed here? As won't be done via backend?
// TODO: Need a 'leave room'/disconnect
function requestJoinRoom(socket, playerName, roomId){
console.log('+ requestJoinRoom recieved');
let room = roomData[roomId];
// Add socket for playerName so that players in room get
// responses, etc. from the room (something like that)
// Add player to socket object, so it can be referred to
// as each socket is individual to a player, but rooms need to
// emit to multiple players. These .player can be used in loops
// https://socket.io/docs/v4/rooms/
// https://stackoverflow.com/a/18096649
socket.playerId = playerName;
if(room === undefined){
io.to(socket.id).emit('responseRoom', 'error');
console.log('>> Room does not exist');
}
let roomName = 'Room_' + roomId;
let people = room['people'];
// people = io.sockets.adapter.rooms[roomId].length; // This gets the sockets in the room (i.e. the players)
//console.log(util.inspect(io.sockets.adapter.rooms, true, 4, true))
//console.log('- people(socket: '+io.sockets.adapter.rooms[player]+')');
//console.log('- maxPlayersPerRoom: '+maxPlayersPerRoom);
if(isUserInRoom(playerName, roomId)){
console.log('Already in room');
return false;
}
if (people < maxPlayersPerRoom) {
// Update people in room count
people = room['people'] += 1;
// Add playerId to room (playerName for now while Ids don't exist TODO)
room['playerIds'][playerName] = playerName;
// https://socket.io/docs/v4/rooms/
// https://stackoverflow.com/a/25028953
socket.join(roomId);
// https://stackoverflow.com/a/25028953
//console.log(util.inspect(io.sockets.adapter.rooms.get(roomId), true, 4, true))
/*
let clients = io.sockets.adapter.rooms.get(roomId);
let numClients = clients ? clients.size : 0;
for (const clientId of clients) {
//this is the socket of each client in the room.
const clientSocket = io.sockets.sockets.get(clientId);
console.log(clientSocket.playerId); // The playerId set beggining of func.
}
*/
console.log('>> User ' + playerName +
' connected on ' + roomName + ' (' + (people) + '/' + maxPlayersPerRoom + ')');
// Joined room (emit to the player that just joined)
io.to(socket.id).emit('responseJoinRoom', roomName);
if (people >= maxPlayersPerRoom) {
console.log('- starting game');
// startGame for room
startGame(roomId);
}
}
}
// Will need to be different to playerName in future (in case dupes)
// would use playerId TODO
function isUserInRoom(playerName, roomId){
if(playerName in roomData[roomId]['playerIds']){
return true;
}
return false;
}
function startGame(roomId){
console.log('>> Room: ' + roomId + ': Requesting game...');
let people = roomData[roomId].players;
/*
try {
//people = io.sockets.adapter.rooms.get(roomId).size;
} catch (e) {
console.log('>> Room: ' + roomId + ': No people here...');
return;
}
*/
// For now, if there's 2 people only. Will need changing for
// 3v1, 5v1, 2v2, etc...
let response = {success: false, message: 'Failed requestStartGame() server.js'};
if(people < maxPlayersPerRoom){
console.log('Too few people');
}
console.log('>> Room: ' + roomId + ': Starting');
// https://stackoverflow.com/a/25028953
//console.log(util.inspect(io.sockets.adapter.rooms.get(roomId), true, 4, true))
let clients = io.sockets.adapter.rooms.get(roomId);
/*
for (const clientId of clients) {
//this is the socket of each client in the room.
const clientSocket = io.sockets.sockets.get(clientId);
console.log(clientSocket.playerId); // The playerId set in requestJoin
// Just so I know how to access stuff in future.
console.log(roomData[roomId].playerIds[clientSocket.playerId] + 'is in the game');
}
*/
// This should return the deck data, etc. for each client
// ideally only returning the items that the user can/should
// see i.e. shouldn't give them the inDeck card list just a counter
// shouldn't have opponent card data/their hand shouldn't be flipped
roomMod.roomGeneration().then(data => {
response.success = true;
response.message = data;
// Each player then gets the roomGeneration stuff
for (const clientId of clients) {
const clientSocket = io.sockets.sockets.get(clientId);
console.log('>> responseStartGame: '+clientSocket.playerId);
// Emit to client socket
io.to(clientSocket.id).emit('responseStartGame', response);
}
})
.catch(err => {
response.message = err;
// Each player then gets the error message
for (const clientId of clients) {
const clientSocket = io.sockets.sockets.get(clientId);
// Emit to client socket
io.to(clientSocket.id).emit('responseStartGame', err);
}
}); });
} }
// Then do functions like this? // Globals for easier clientside alerts/logs, etc.
function shuffleDeck(roomId, playerId){ global.socketAlert = function(socket, message, type = 'alert'){
global.io.to(socket).emit(
type, {'message': message}
);
} }

Loading…
Cancel
Save