mirror of
https://github.com/MaciejkaG/statki.git
synced 2024-11-30 00:32:55 +01:00
Major changes
- Functioning lobbies with redirection to the board view - Partly working game mechanics
This commit is contained in:
parent
a6d6d6b570
commit
302fe3d328
193
index.js
193
index.js
@ -6,6 +6,7 @@ import { fileURLToPath } from 'node:url';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import session from "express-session";
|
||||
import { engine } from 'express-handlebars';
|
||||
import { createClient } from 'redis';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
@ -21,6 +22,11 @@ app.set('views', './views');
|
||||
|
||||
const server = createServer(app);
|
||||
const io = new Server(server);
|
||||
const redis = createClient();
|
||||
redis.on('error', err => console.log('Redis Client Error', err));
|
||||
await redis.connect();
|
||||
|
||||
var gameData = [];
|
||||
|
||||
app.set('trust proxy', 1);
|
||||
const sessionMiddleware = session({
|
||||
@ -34,7 +40,7 @@ app.use(express.static(path.join(__dirname, 'public')));
|
||||
|
||||
io.engine.use(sessionMiddleware);
|
||||
|
||||
app.get("/", (req, res) => {
|
||||
app.get("/", async (req, res) => {
|
||||
if (req.session.nickname == null) {
|
||||
res.redirect("/setup");
|
||||
} else {
|
||||
@ -50,14 +56,26 @@ app.get("/setup", (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/api/setup-profile', function (req, res) {
|
||||
app.post('/api/setup-profile', (req, res) => {
|
||||
if (req.session.nickname == null && 4 < req.body.nickname.length && req.body.nickname.length < 16) {
|
||||
req.session.nickname = req.body.nickname;
|
||||
req.session.playerID = uuidv4();
|
||||
}
|
||||
|
||||
res.redirect("/")
|
||||
});
|
||||
|
||||
app.get("/game", async (req, res) => {
|
||||
const game = await redis.json.get(`game:${req.query.id}`);
|
||||
if (req.session.nickname == null) {
|
||||
res.redirect("/setup");
|
||||
} else if (req.query.id == null || game == null || game.state == "expired") {
|
||||
res.status(400).send('badGameId');
|
||||
} else {
|
||||
res.render('board');
|
||||
}
|
||||
});
|
||||
|
||||
app.get("/*", (req, res) => {
|
||||
res.redirect("/?path=" + req.originalUrl);
|
||||
});
|
||||
@ -69,59 +87,113 @@ io.on('connection', (socket) => {
|
||||
return;
|
||||
}
|
||||
|
||||
socket.on('create lobby', (callback) => {
|
||||
if (socket.rooms.size === 1) {
|
||||
let id = genID();
|
||||
callback({
|
||||
status: "ok",
|
||||
gameCode: id
|
||||
});
|
||||
console.log(isPlayerInGame(socket));
|
||||
if (!isPlayerInGame(socket)) {
|
||||
socket.on('whats my nick', (callback) => {
|
||||
callback(session.nickname);
|
||||
});
|
||||
|
||||
socket.join(id);
|
||||
} else {
|
||||
callback({
|
||||
status: "alreadyInLobby",
|
||||
gameCode: socket.rooms[1]
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('join lobby', (msg, callback) => {
|
||||
if (io.sockets.adapter.rooms.get(msg) == null) {
|
||||
callback({
|
||||
status: "bad_id"
|
||||
});
|
||||
} else {
|
||||
socket.on('create lobby', (callback) => {
|
||||
if (socket.rooms.size === 1) {
|
||||
io.to(msg).emit("joined", session.nickname);
|
||||
let opp = io.sockets.sockets.get(io.sockets.adapter.rooms.get(msg).values().next().value);
|
||||
let oppNickname = opp.request.session.nickname;
|
||||
socket.join(msg);
|
||||
let id = genID();
|
||||
callback({
|
||||
status: "ok",
|
||||
oppNickname: oppNickname,
|
||||
gameCode: id
|
||||
});
|
||||
|
||||
socket.join(id);
|
||||
} else {
|
||||
callback({
|
||||
status: "alreadyInLobby",
|
||||
gameCode: id,
|
||||
gameCode: socket.rooms[1]
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('leave lobby', (callback) => {
|
||||
if (socket.rooms.size === 2) {
|
||||
socket.leave(socket.rooms[1]);
|
||||
callback({
|
||||
status: "ok"
|
||||
});
|
||||
} else {
|
||||
callback({
|
||||
status: "youreNotInLobby"
|
||||
});
|
||||
}
|
||||
});
|
||||
socket.on('join lobby', (msg, callback) => {
|
||||
if (io.sockets.adapter.rooms.get(msg) == null || io.sockets.adapter.rooms.get(msg).size > 1) {
|
||||
callback({
|
||||
status: "bad_id"
|
||||
});
|
||||
} else {
|
||||
if (socket.rooms.size === 1) {
|
||||
io.to(msg).emit("joined", session.nickname); // Wyślij hostowi powiadomienie o dołączającym graczu
|
||||
// Zmienna opp zawiera socket hosta
|
||||
let opp = io.sockets.sockets.get(io.sockets.adapter.rooms.get(msg).values().next().value);
|
||||
let oppNickname = opp.request.session.nickname;
|
||||
|
||||
socket.join(msg); // Dołącz gracza do grupy
|
||||
callback({
|
||||
status: "ok",
|
||||
oppNickname: oppNickname,
|
||||
}); // Wyślij dołączonemu graczowi odpowiedź
|
||||
|
||||
// Teraz utwórz objekt partii w trakcie w bazie Redis
|
||||
const gameId = uuidv4();
|
||||
redis.json.set(`game:${gameId}`, '$', {
|
||||
state: "pregame",
|
||||
boards: {
|
||||
host: { // typ 2 to trójmasztowiec pozycja i obrót na planszy które pola zostały trafione
|
||||
ships: [], // zawiera np. {type: 2, posX: 3, posY: 4, rot: 2, hits: [false, false, true]}
|
||||
// pozycja na planszy czy strzał miał udział w zatopieniu statku?
|
||||
shots: [], // zawiera np. {posX: 3, posY: 5, sunk: true}
|
||||
},
|
||||
guest: {
|
||||
ships: [],
|
||||
shots: [],
|
||||
}
|
||||
},
|
||||
nextPlayer: 0,
|
||||
});
|
||||
|
||||
io.to(msg).emit("gameReady", gameId);
|
||||
|
||||
io.sockets.clients(msg).forEach((s) => {
|
||||
s.leave(msg);
|
||||
});
|
||||
} else {
|
||||
callback({
|
||||
status: "alreadyInLobby",
|
||||
gameCode: id,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('leave lobby', (callback) => {
|
||||
if (socket.rooms.size === 2) {
|
||||
socket.leave(socket.rooms[1]);
|
||||
io.to(socket.rooms[1]).emit("player left");
|
||||
callback({
|
||||
status: "ok"
|
||||
});
|
||||
} else {
|
||||
callback({
|
||||
status: "youreNotInLobby"
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('disconnecting', () => {
|
||||
if (isPlayerInRoom(socket)) {
|
||||
io.to(socket.rooms[1]).emit("player left");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
socket.on('shoot', () => {
|
||||
const playerGame = getPlayerGameData(socket);
|
||||
|
||||
if (playerGame.state === "action") {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('disconnecting', () => {
|
||||
if (isPlayerInRoom(socket)) {
|
||||
io.to(socket.rooms).emit("player left");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
server.listen(7777, () => {
|
||||
@ -130,4 +202,37 @@ server.listen(7777, () => {
|
||||
|
||||
function genID() {
|
||||
return Math.floor(100000 + Math.random() * 900000).toString();
|
||||
}
|
||||
|
||||
// async function emitToParty(partyuuid) {
|
||||
// const party = gameData.find((element) => element.partyId===partyuuid);
|
||||
|
||||
// if (party!==null) {
|
||||
// party.members.forEach(socketId => {
|
||||
|
||||
// io.to(socketId).emit();
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
function isPlayerInRoom(socket) {
|
||||
return !socket.rooms.size === 1;
|
||||
}
|
||||
|
||||
async function isPlayerInGame(socket) {
|
||||
const room = getPlayerRoom(socket);
|
||||
|
||||
const game = await redis.json.get(`game:${room}`);
|
||||
return game != null;
|
||||
}
|
||||
|
||||
function getPlayerGameData(socket) {
|
||||
const room = getPlayerRoom(socket);
|
||||
|
||||
const game = redis.json.get(`game:${room}`);
|
||||
return game;
|
||||
}
|
||||
|
||||
function getPlayerRoom(socket) {
|
||||
return socket.rooms.values().next().value;
|
||||
}
|
88
package-lock.json
generated
88
package-lock.json
generated
@ -12,6 +12,7 @@
|
||||
"express": "^4.18.2",
|
||||
"express-handlebars": "^7.1.2",
|
||||
"express-session": "^1.17.3",
|
||||
"redis": "^4.6.12",
|
||||
"socket.io": "^4.7.2",
|
||||
"uuid": "^9.0.1",
|
||||
"uuid4": "^2.0.3"
|
||||
@ -42,6 +43,59 @@
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/@redis/bloom": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz",
|
||||
"integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==",
|
||||
"peerDependencies": {
|
||||
"@redis/client": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@redis/client": {
|
||||
"version": "1.5.13",
|
||||
"resolved": "https://registry.npmjs.org/@redis/client/-/client-1.5.13.tgz",
|
||||
"integrity": "sha512-epkUM9D0Sdmt93/8Ozk43PNjLi36RZzG+d/T1Gdu5AI8jvghonTeLYV69WVWdilvFo+PYxbP0TZ0saMvr6nscQ==",
|
||||
"dependencies": {
|
||||
"cluster-key-slot": "1.1.2",
|
||||
"generic-pool": "3.9.0",
|
||||
"yallist": "4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/@redis/graph": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.1.tgz",
|
||||
"integrity": "sha512-FEMTcTHZozZciLRl6GiiIB4zGm5z5F3F6a6FZCyrfxdKOhFlGkiAqlexWMBzCi4DcRoyiOsuLfW+cjlGWyExOw==",
|
||||
"peerDependencies": {
|
||||
"@redis/client": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@redis/json": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.6.tgz",
|
||||
"integrity": "sha512-rcZO3bfQbm2zPRpqo82XbW8zg4G/w4W3tI7X8Mqleq9goQjAGLL7q/1n1ZX4dXEAmORVZ4s1+uKLaUOg7LrUhw==",
|
||||
"peerDependencies": {
|
||||
"@redis/client": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@redis/search": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.6.tgz",
|
||||
"integrity": "sha512-mZXCxbTYKBQ3M2lZnEddwEAks0Kc7nauire8q20oA0oA/LoA+E/b5Y5KZn232ztPb1FkIGqo12vh3Lf+Vw5iTw==",
|
||||
"peerDependencies": {
|
||||
"@redis/client": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@redis/time-series": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.5.tgz",
|
||||
"integrity": "sha512-IFjIgTusQym2B5IZJG3XKr5llka7ey84fw/NOYqESP5WUfQs9zz1ww/9+qoz4ka/S6KcGBodzlCeZ5UImKbscg==",
|
||||
"peerDependencies": {
|
||||
"@redis/client": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@socket.io/component-emitter": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz",
|
||||
@ -185,6 +239,14 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/cluster-key-slot": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz",
|
||||
"integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
@ -543,6 +605,14 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/generic-pool": {
|
||||
"version": "3.9.0",
|
||||
"resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz",
|
||||
"integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==",
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/get-intrinsic": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz",
|
||||
@ -961,6 +1031,19 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/redis": {
|
||||
"version": "4.6.12",
|
||||
"resolved": "https://registry.npmjs.org/redis/-/redis-4.6.12.tgz",
|
||||
"integrity": "sha512-41Xuuko6P4uH4VPe5nE3BqXHB7a9lkFL0J29AlxKaIfD6eWO8VO/5PDF9ad2oS+mswMsfFxaM5DlE3tnXT+P8Q==",
|
||||
"dependencies": {
|
||||
"@redis/bloom": "1.2.0",
|
||||
"@redis/client": "1.5.13",
|
||||
"@redis/graph": "1.1.1",
|
||||
"@redis/json": "1.0.6",
|
||||
"@redis/search": "1.1.6",
|
||||
"@redis/time-series": "1.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
@ -1454,6 +1537,11 @@
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
"express": "^4.18.2",
|
||||
"express-handlebars": "^7.1.2",
|
||||
"express-session": "^1.17.3",
|
||||
"redis": "^4.6.12",
|
||||
"socket.io": "^4.7.2",
|
||||
"uuid": "^9.0.1",
|
||||
"uuid4": "^2.0.3"
|
||||
|
@ -16,6 +16,10 @@
|
||||
color: rgb(136, 136, 136)
|
||||
}
|
||||
|
||||
#gameView {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
body {
|
||||
background: black;
|
||||
color: white;
|
||||
@ -163,4 +167,20 @@ h1,h2,h3,h4,h5,h6 {
|
||||
|
||||
#selectedShip {
|
||||
animation: changingIn 1 0.2s ease;
|
||||
}
|
||||
|
||||
.cover {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
background: rgb(0, 0, 0, 0.4);
|
||||
backdrop-filter: blur(20px);
|
||||
transition: opacity 0.5s;
|
||||
z-index: 999;
|
||||
}
|
6
public/assets/js/socket-game.js
Normal file
6
public/assets/js/socket-game.js
Normal file
@ -0,0 +1,6 @@
|
||||
const socket = io();
|
||||
|
||||
socket.on("players ready", () => {
|
||||
$(".cover").css({opacity: 0, pointerEvents: "none"});
|
||||
socket.emit("shoot");
|
||||
});
|
@ -7,6 +7,35 @@ socket.on("joined", (nick) => {
|
||||
lockUI(false);
|
||||
});
|
||||
|
||||
socket.on("player left", () => {
|
||||
lockUI(true);
|
||||
switchView("mainMenuView");
|
||||
lockUI(false);
|
||||
});
|
||||
|
||||
socket.on("gameReady", (gameId) => {
|
||||
setTimeout(() => {
|
||||
window.location.replace("/game?id=" + gameId);
|
||||
}, 2000);
|
||||
});
|
||||
|
||||
var nickname;
|
||||
|
||||
socket.emit("whats my nick", (myNickname) => {
|
||||
nickname = myNickname;
|
||||
});
|
||||
|
||||
socket.on("game start", (gameInfo) => {
|
||||
let opp;
|
||||
if (gameInfo.players[0]!==nickname) {
|
||||
opp = gameInfo.players[0];
|
||||
} else {
|
||||
opp = gameInfo.players[1];
|
||||
}
|
||||
|
||||
alert(`Grasz przeciwko: ${opp}`);
|
||||
});
|
||||
|
||||
$("#createGameButton").on("click", function () {
|
||||
lockUI(true);
|
||||
socket.emit("create lobby", (response) => {
|
||||
|
34
views/board.handlebars
Normal file
34
views/board.handlebars
Normal file
@ -0,0 +1,34 @@
|
||||
<div class="cover">
|
||||
<h1>Oczekiwanie na przeciwnika...</h1>
|
||||
</div>
|
||||
|
||||
<div class="container" id="gameView">
|
||||
<div>
|
||||
<h1>Statki</h1>
|
||||
<div class="panelContainer">
|
||||
<div class="shapes">
|
||||
<div class="ownBoardInfo">
|
||||
<h3>Wybrany statek</h3>
|
||||
<h2 class="dynamic" id="selectedShip">Jednomasztowiec</h2>
|
||||
<h3>Dostępne: <span class="dynamic danger">1</span></h3>
|
||||
</div>
|
||||
<span class="break"></span>
|
||||
<h2>Sterowanie</h2>
|
||||
<h3 class="controlsOwnBoard"><span class="important">S</span> Zmiana statku</h3>
|
||||
<h3 class="controlsOwnBoard"><span class="important">R</span> Obrót statku</h3>
|
||||
<h3><span class="important">B</span> Zamiana planszy</h3>
|
||||
<span class="break"></span>
|
||||
<h3>Ruch: <span class="dynamic">Przeciwnik</span></h3>
|
||||
<h2 class="important">∞</h2>
|
||||
</div>
|
||||
<div class="boardContainer">
|
||||
<div id="board" oncontextmenu="return false;"></div>
|
||||
<div id="secondaryBoard" class="secondary" oncontextmenu="return false;"></div>
|
||||
</div>
|
||||
<div class="spaceFiller"></div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/assets/js/battleships_lib.js"></script>
|
||||
<script src="/assets/js/main.js"></script>
|
||||
<script src="/assets/js/key_handling.js"></script>
|
||||
</div>
|
@ -77,36 +77,5 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container" id="gameView" data-title="Statki / Gra" data-path="/game">
|
||||
<div>
|
||||
<h1>Statki</h1>
|
||||
<div class="panelContainer">
|
||||
<div class="shapes">
|
||||
<div class="ownBoardInfo">
|
||||
<h3>Wybrany statek</h3>
|
||||
<h2 class="dynamic" id="selectedShip">Jednomasztowiec</h2>
|
||||
<h3>Dostępne: <span class="dynamic danger">1</span></h3>
|
||||
</div>
|
||||
<span class="break"></span>
|
||||
<h2>Sterowanie</h2>
|
||||
<h3 class="controlsOwnBoard"><span class="important">S</span> Zmiana statku</h3>
|
||||
<h3 class="controlsOwnBoard"><span class="important">R</span> Obrót statku</h3>
|
||||
<h3><span class="important">B</span> Zamiana planszy</h3>
|
||||
<span class="break"></span>
|
||||
<h3>Ruch: <span class="dynamic">Przeciwnik</span></h3>
|
||||
<h2 class="important">∞</h2>
|
||||
</div>
|
||||
<div class="boardContainer">
|
||||
<div id="board" oncontextmenu="return false;"></div>
|
||||
<div id="secondaryBoard" class="secondary" oncontextmenu="return false;"></div>
|
||||
</div>
|
||||
<div class="spaceFiller"></div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/assets/js/battleships_lib.js"></script>
|
||||
<script src="/assets/js/main.js"></script>
|
||||
<script src="/assets/js/key_handling.js"></script>
|
||||
</div>
|
||||
|
||||
<script src="/assets/js/socket.js"></script>
|
||||
<script src="/assets/js/spa_lib.js"></script>
|
Loading…
Reference in New Issue
Block a user