redoing how i deal with turns
This commit is contained in:
27
README.md
27
README.md
@@ -5,21 +5,34 @@ SEE BELOW FOR CONFIGURATION GUIDE
|
|||||||
|
|
||||||
### Product Description
|
### Product Description
|
||||||
|
|
||||||
https://scrabble.hasbro.com/en-us/rules
|
The following resources were used for the creation of the game's logic:
|
||||||
https://www.zapsplat.com/?s=scrabble
|
* https://scrabble.hasbro.com/en-us/rules
|
||||||
|
* https://www.zapsplat.com/?s=scrabble
|
||||||
|
* https://www.scrabble3d.info/t2342f139-Default-rules.html
|
||||||
|
|
||||||
https://www.scrabble3d.info/t2342f139-Default-rules.html
|
|
||||||
|
|
||||||
|
|
||||||
If the scope allowed for it, every function would be (reasonably) unit tested.
|
|
||||||
|
|
||||||
The solution to locale-ise language in HTML is extremely naive and there are a lot better ways to do it, i did what i could in the time without a full refractor and SSR.
|
The solution to locale-ise language in HTML is extremely naive and there are a lot better ways to do it, i did what i could in the time without a full refractor and SSR.
|
||||||
However it is not at much detriment of readability and maintainability of the code so i didn't deem it neccesary.
|
However it is not at much detriment of readability and maintainability of the code so i didn't deem it neccesary.
|
||||||
|
|
||||||
The locales are stored in different language files so it is easier for people to contribute and thus more maintanable.
|
The locales are stored in different language files so it is easier for people to contribute and thus more maintanable.
|
||||||
|
|
||||||
|
If the scope allowed for it, every function would be (reasonably) unit tested.
|
||||||
|
|
||||||
### Configuration Guide
|
### Configuration Guide
|
||||||
|
|
||||||
|
Make sure your working directory is root/server
|
||||||
|
|
||||||
|
1. run ```npm i```
|
||||||
|
2. run ```npm run setup```
|
||||||
|
3. run ```npm run start```
|
||||||
|
|
||||||
|
If you want a custom port create a .env file and use the variable PORT
|
||||||
|
or just use environment variables
|
||||||
|
|
||||||
|
### Implementation Rationale
|
||||||
|
|
||||||
|
|
||||||
|
### Bugs and Issues
|
||||||
|
|
||||||
### Contributing
|
### Contributing
|
||||||
|
|
||||||
@@ -27,4 +40,6 @@ To contribute a translation
|
|||||||
|
|
||||||
### Acknowledgements
|
### Acknowledgements
|
||||||
|
|
||||||
|
Express.js - HTTP Routing and Management
|
||||||
|
Socket.io - Socket Routing and Management
|
||||||
Inês Filipa Baiõa Antunes - Tranlations (Portuguese, Spanish)
|
Inês Filipa Baiõa Antunes - Tranlations (Portuguese, Spanish)
|
||||||
|
|||||||
1
TODO
1
TODO
@@ -52,6 +52,7 @@
|
|||||||
→ Refactor to code portsoc eslint
|
→ Refactor to code portsoc eslint
|
||||||
→ Refactor game client
|
→ Refactor game client
|
||||||
→ WHY THE HELL ARE THEY CALLED USERS IN SOME PLACES AND PLAYERS IN OTHERS
|
→ WHY THE HELL ARE THEY CALLED USERS IN SOME PLACES AND PLAYERS IN OTHERS
|
||||||
|
→ Why in some places is it user.name and others user.username
|
||||||
|
|
||||||
☐ Bugfixes
|
☐ Bugfixes
|
||||||
→ If a user leaves their current game then makes a new one, it's corrupted
|
→ If a user leaves their current game then makes a new one, it's corrupted
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ function mouseDown(event, element)
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
// disalow picking up of played pieces
|
// disalow picking up of played pieces
|
||||||
if (element.classList.contains('played-piece')) return;
|
if (element.classList.contains('played-piece') || element.classList.contains('locked')) return;
|
||||||
|
|
||||||
piecePickedUp(element);
|
piecePickedUp(element);
|
||||||
|
|
||||||
|
|||||||
@@ -137,11 +137,19 @@ score {
|
|||||||
#game-controls {
|
#game-controls {
|
||||||
border: 1px dotted black;
|
border: 1px dotted black;
|
||||||
|
|
||||||
|
height: 5%;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.game-control {
|
||||||
|
background-color: #A79AFF;
|
||||||
|
color: white;
|
||||||
|
flex-grow: 2;
|
||||||
|
}
|
||||||
|
|
||||||
#moves {
|
#moves {
|
||||||
border: 1px dotted black;
|
border: 1px dotted black;
|
||||||
|
|||||||
@@ -312,9 +312,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="connection-state"><script>document.write(localeString('status'))</script>:</div>
|
<div class="connection-state"><script>document.write(localeString('status'))</script>:</div>
|
||||||
<div id="game-controls">
|
<div id="game-controls">
|
||||||
<input class="button-exchange" type="button" value="Exchange tiles" onclick="onExchangeTiles()">
|
<input class="game-control button-exchange" type="button" value="Exchange tiles" onclick="onExchangeTiles()">
|
||||||
<input class="button-skip" type="button" value="Skip turn" onclick="onSkipTurn()">
|
<input class="game-control button-skip" type="button" value="Skip turn" onclick="onSkipTurn()">
|
||||||
<input class="button-play" type="button" value="Play turn" onclick="onPlayTurn()">
|
<input class="game-control button-play" type="button" value="Play turn" onclick="onPlayTurn()">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -328,9 +328,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="game-controls">
|
<div id="game-controls">
|
||||||
<input class="button-exchange" type="button" value="Exchange tiles" onclick="onExchangeTiles()">
|
<input class="game-control button-exchange" type="button" value="Exchange tiles" onclick="onExchangeTiles()">
|
||||||
<input class="button-skip" type="button" value="Skip turn" onclick="onSkipTurn()">
|
<input class="game-control button-skip" type="button" value="Skip turn" onclick="onSkipTurn()">
|
||||||
<input class="button-play" type="button" value="Play turn" onclick="onPlayTurn()">
|
<input class="game-control button-play" type="button" value="Play turn" onclick="onPlayTurn()">
|
||||||
</div>
|
</div>
|
||||||
<div id="moves">
|
<div id="moves">
|
||||||
<div class="move">Jerry played OXYPHENBUTAZONE for 40 points</div>
|
<div class="move">Jerry played OXYPHENBUTAZONE for 40 points</div>
|
||||||
|
|||||||
@@ -33,6 +33,10 @@ function initUI()
|
|||||||
IPlayButton.forEach(e => {
|
IPlayButton.forEach(e => {
|
||||||
e.disabled = true;
|
e.disabled = true;
|
||||||
});
|
});
|
||||||
|
if (MyTurn)
|
||||||
|
startMyTurnUI();
|
||||||
|
else
|
||||||
|
stopMyTurnUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
const UserUIReplacer = (p, u, n, s) => `<div class="p${p} player${u} player">
|
const UserUIReplacer = (p, u, n, s) => `<div class="p${p} player${u} player">
|
||||||
@@ -88,6 +92,10 @@ function updateUsersUI(users)
|
|||||||
|
|
||||||
function startMyTurnUI()
|
function startMyTurnUI()
|
||||||
{
|
{
|
||||||
|
for (const piece of document.querySelectorAll('piece, nopiece'))
|
||||||
|
{
|
||||||
|
piece.classList.remove('locked');
|
||||||
|
}
|
||||||
IExchangeButton.forEach(e => {
|
IExchangeButton.forEach(e => {
|
||||||
e.disabled = false;
|
e.disabled = false;
|
||||||
});
|
});
|
||||||
@@ -97,14 +105,14 @@ function startMyTurnUI()
|
|||||||
IPlayButton.forEach(e => {
|
IPlayButton.forEach(e => {
|
||||||
e.disabled = false;
|
e.disabled = false;
|
||||||
});
|
});
|
||||||
document.querySelectorAll('.unplayed-piece').forEach(e => {
|
|
||||||
if (e.classList.contains('played-piece'))
|
|
||||||
e.classList.remove('played-piece');
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function stopMyTurnUI()
|
function stopMyTurnUI()
|
||||||
{
|
{
|
||||||
|
for (const piece of document.querySelectorAll('piece, nopiece'))
|
||||||
|
{
|
||||||
|
piece.classList.add('locked');
|
||||||
|
}
|
||||||
IExchangeButton.forEach(e => {
|
IExchangeButton.forEach(e => {
|
||||||
e.disabled = true;
|
e.disabled = true;
|
||||||
});
|
});
|
||||||
@@ -114,10 +122,6 @@ function stopMyTurnUI()
|
|||||||
IPlayButton.forEach(e => {
|
IPlayButton.forEach(e => {
|
||||||
e.disabled = true;
|
e.disabled = true;
|
||||||
});
|
});
|
||||||
document.querySelectorAll('.unplayed-piece').forEach(e => {
|
|
||||||
if (!e.classList.contains('played-piece'))
|
|
||||||
e.classList.add('played-piece');
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onExchangeTiles()
|
function onExchangeTiles()
|
||||||
|
|||||||
@@ -181,9 +181,10 @@ function BeginGame(lobby)
|
|||||||
{
|
{
|
||||||
let t, r;
|
let t, r;
|
||||||
do {
|
do {
|
||||||
|
// TODO: this goes out of range
|
||||||
r = Math.floor(Math.random() * tilebag.length + 1);
|
r = Math.floor(Math.random() * tilebag.length + 1);
|
||||||
t = tilebag[r];
|
t = tilebag[r];
|
||||||
} while (t === null)
|
} while (t === undefined)
|
||||||
tilebag.splice(r, 1);
|
tilebag.splice(r, 1);
|
||||||
players[player].activetiles.push(t);
|
players[player].activetiles.push(t);
|
||||||
}
|
}
|
||||||
@@ -260,28 +261,37 @@ NOTES
|
|||||||
function PlayTurn(gameuid, playeruid, turn)
|
function PlayTurn(gameuid, playeruid, turn)
|
||||||
{
|
{
|
||||||
const game = ActiveGames[gameuid];
|
const game = ActiveGames[gameuid];
|
||||||
|
|
||||||
ActiveGames[gameuid].gamestates.push(turn);
|
|
||||||
|
|
||||||
const turninfo = gameNextTurn(gameuid);
|
const turninfo = gameNextTurn(gameuid);
|
||||||
|
|
||||||
|
ActiveGames[gameuid].gamestates.push(turn);
|
||||||
|
|
||||||
|
// give user new tiles
|
||||||
|
|
||||||
|
console.log(game);
|
||||||
return [turn, turninfo];
|
return [turn, turninfo];
|
||||||
}
|
}
|
||||||
|
|
||||||
function SkipTurn(gameuid, playeruid)
|
function SkipTurn(gameuid, playeruid)
|
||||||
{
|
{
|
||||||
gameNextTurn(gameuid);
|
const turninfo = gameNextTurn(gameuid);
|
||||||
|
// get last game state
|
||||||
|
const turn = {
|
||||||
|
playeruid:
|
||||||
|
};
|
||||||
|
|
||||||
|
return [turn, turninfo];
|
||||||
}
|
}
|
||||||
|
|
||||||
function gameNextTurn(gameuid)
|
function gameNextTurn(gameuid)
|
||||||
{
|
{
|
||||||
const PlayerCount = ActiveGames[gameuid].players.length;
|
const playerCount = ActiveGames[gameuid].players.length;
|
||||||
ActiveGames[gameuid].turn++;
|
let newTurn = ActiveGames[gameuid].turn += 1;
|
||||||
ActiveGames[gameuid].turn %= PlayerCount;
|
newTurn = ActiveGames[gameuid].turn % PlayerCount;
|
||||||
ActiveGames[gameuid].turntotal++;
|
const newTotalTurn = ActiveGames[gameuid].turntotal += 1;
|
||||||
return {
|
return {
|
||||||
// i forgot why this is an object, there's more attributes i forgot about
|
|
||||||
turnplayer: ActiveGames[gameuid].players[ActiveGames[gameuid].turn],
|
turnplayer: ActiveGames[gameuid].players[ActiveGames[gameuid].turn],
|
||||||
|
newTurn: newTurn,
|
||||||
|
newTotalTurn: newTotalTurn
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -401,17 +401,27 @@ function GamePlayTurn(socket, args)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.game(`USER ${user.uid} (${user.name}) IS ATTEMPTING TO PLAY A TURN IN GAME ${game.uid}`);
|
Logger.game(`USER ${user.uid} (${user.username}) IS ATTEMPTING TO PLAY A TURN IN GAME ${game.uid}`);
|
||||||
|
|
||||||
if (args.skip === true)
|
if (args.skip === true)
|
||||||
{
|
{
|
||||||
const {outcome, turninfo} = Game.Logic.SkipTurn(game.uid, user.uid);
|
const [outcome, turninfo] = Game.Logic.SkipTurn(game.uid, user.uid);
|
||||||
|
io.to(game.uid).emit('game-turn-processed', {
|
||||||
|
outcome: outcome
|
||||||
|
});
|
||||||
|
|
||||||
|
const nextuser = Game.Registrar.GetConnectionByUser(turninfo.turnplayer.uid);
|
||||||
|
|
||||||
|
io.to(game.uid).emit('game-turn-start', {
|
||||||
|
turninfo: turninfo
|
||||||
|
});
|
||||||
|
|
||||||
|
io.to(nextuser).emit('game-your-turn');
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
// TODO: validate args
|
// TODO: validate args
|
||||||
const [outcome, turninfo] = Game.Logic.PlayTurn(game.uid, user.uid, args)
|
const [outcome, turninfo] = Game.Logic.PlayTurn(game.uid, user.uid, args)
|
||||||
|
|
||||||
// give user new tiles
|
|
||||||
// process errorsq
|
// process errorsq
|
||||||
|
|
||||||
io.to(game.uid).emit('game-turn-processed', {
|
io.to(game.uid).emit('game-turn-processed', {
|
||||||
|
|||||||
Reference in New Issue
Block a user