move to public repo
This commit is contained in:
29
server/package.json
Normal file
29
server/package.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"main": "./dist/server/src/server.js",
|
||||
"scripts": {
|
||||
"start": "node ./dist/server/src/server.js",
|
||||
"build": "tsc",
|
||||
"dev": "ts-node-dev src/server.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"chess.js": "^1.0.0-alpha.0",
|
||||
"connect-pg-simple": "^8.0.0",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^16.0.3",
|
||||
"express": "^4.18.2",
|
||||
"express-session": "^1.17.3",
|
||||
"nanoid": "^3.3.4",
|
||||
"pg": "^8.8.0",
|
||||
"socket.io": "^4.5.4",
|
||||
"xss": "^1.0.14"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/connect-pg-simple": "^7.0.0",
|
||||
"@types/express": "^4.17.15",
|
||||
"@types/express-session": "^1.17.5",
|
||||
"@types/node": "^18.11.18",
|
||||
"@types/pg": "^8.6.6",
|
||||
"ts-node-dev": "^2.0.0",
|
||||
"typescript": "^4.9.4"
|
||||
}
|
||||
}
|
||||
51
server/src/controllers/auth.controller.ts
Normal file
51
server/src/controllers/auth.controller.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import type { Request, Response } from "express";
|
||||
import type { User } from "@types";
|
||||
import xss from "xss";
|
||||
|
||||
export const getCurrentSession = async (req: Request, res: Response) => {
|
||||
try {
|
||||
if (req.session.user) {
|
||||
res.status(200).json(req.session.user);
|
||||
} else {
|
||||
res.status(404).end();
|
||||
}
|
||||
} catch (err: unknown) {
|
||||
console.log(err);
|
||||
res.status(500).end();
|
||||
}
|
||||
};
|
||||
|
||||
export const guestSession = async (req: Request, res: Response) => {
|
||||
try {
|
||||
const name = xss(req.body.name);
|
||||
|
||||
if (!req.session.user || !req.session.user?.id) {
|
||||
// create guest session
|
||||
const user: User = {
|
||||
id: req.session.id,
|
||||
name
|
||||
};
|
||||
req.session.user = user;
|
||||
} else if (typeof req.session.user.id === "string" && req.session.user.name !== name) {
|
||||
// update guest name
|
||||
req.session.user.name = name;
|
||||
}
|
||||
req.session.save(() => {
|
||||
res.status(201).json(req.session.user);
|
||||
});
|
||||
} catch (err: unknown) {
|
||||
console.log(err);
|
||||
res.status(500).end();
|
||||
}
|
||||
};
|
||||
|
||||
export const logoutSession = async (req: Request, res: Response) => {
|
||||
try {
|
||||
req.session.destroy(() => {
|
||||
res.status(204).end();
|
||||
});
|
||||
} catch (err: unknown) {
|
||||
console.log(err);
|
||||
res.status(500).end();
|
||||
}
|
||||
};
|
||||
74
server/src/controllers/games.controller.ts
Normal file
74
server/src/controllers/games.controller.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import type { Request, Response } from "express";
|
||||
import { activeGames } from "../db/models/game.model";
|
||||
import type { Game, User } from "@types";
|
||||
import { nanoid } from "nanoid";
|
||||
|
||||
export const getActiveGames = async (req: Request, res: Response) => {
|
||||
try {
|
||||
//if (!req.query || !req.query.code) {
|
||||
res.status(200).json(activeGames);
|
||||
//}
|
||||
|
||||
/*
|
||||
// todo: if code query is URL, convert to code (or do it on client side?)
|
||||
const code =
|
||||
(req.query.code as string).startsWith("http") ||
|
||||
(req.query.code as string).startsWith("ches.su")
|
||||
? path.posix.basename(url.parse(req.query.code as string).pathname as string)
|
||||
: req.query.code;
|
||||
|
||||
console.log(code);
|
||||
const game = activeGames.find((g) => g.code === code);
|
||||
|
||||
if (!game) {
|
||||
res.status(404).end();
|
||||
} else {
|
||||
res.status(200).json(game);
|
||||
}*/
|
||||
} catch (err: unknown) {
|
||||
console.log(err);
|
||||
res.status(500).end();
|
||||
}
|
||||
};
|
||||
|
||||
export const createGame = async (req: Request, res: Response) => {
|
||||
try {
|
||||
if (!req.session.user) {
|
||||
console.log("unauthorized createGame:");
|
||||
console.log(req.session);
|
||||
res.status(401).end();
|
||||
return;
|
||||
}
|
||||
const user: User = req.session.user;
|
||||
const game: Game = {
|
||||
code: nanoid(6),
|
||||
open: true,
|
||||
host: user
|
||||
};
|
||||
if (req.body.side === "white") {
|
||||
game.white = user;
|
||||
} else if (req.body.side === "black") {
|
||||
game.black = user;
|
||||
} else {
|
||||
// random
|
||||
if (Math.floor(Math.random() * 2) === 0) {
|
||||
game.white = user;
|
||||
} else {
|
||||
game.black = user;
|
||||
}
|
||||
}
|
||||
activeGames.push(game);
|
||||
|
||||
res.status(201).json({ code: game.code });
|
||||
} catch (err: unknown) {
|
||||
console.log(err);
|
||||
res.status(500).end();
|
||||
}
|
||||
};
|
||||
|
||||
// use sockets for joining games
|
||||
/*
|
||||
export const joinGame = async (req: Request, res: Response) => {
|
||||
console.log("joining game!");
|
||||
};
|
||||
*/
|
||||
3
server/src/db/index.ts
Normal file
3
server/src/db/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { Pool } from "pg";
|
||||
|
||||
export const db = new Pool();
|
||||
16
server/src/db/init.sql
Normal file
16
server/src/db/init.sql
Normal file
@@ -0,0 +1,16 @@
|
||||
-- users
|
||||
CREATE TABLE "user" (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(128) UNIQUE NOT NULL,
|
||||
email VARCHAR(128),
|
||||
password TEXT
|
||||
);
|
||||
|
||||
-- games
|
||||
CREATE TABLE "game" (
|
||||
id SERIAL PRIMARY KEY,
|
||||
pgn TEXT,
|
||||
white_id INT REFERENCES "user",
|
||||
black_id INT REFERENCES "user",
|
||||
winner CHAR(5)
|
||||
);
|
||||
89
server/src/db/models/game.model.ts
Normal file
89
server/src/db/models/game.model.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import { db } from "..";
|
||||
import { Game } from "@types";
|
||||
|
||||
export const activeGames: Array<Game> = [];
|
||||
|
||||
// todo: join user and game relationship
|
||||
|
||||
const create = async (game: Game) => {
|
||||
try {
|
||||
const res = await db.query(
|
||||
`INSERT INTO "game"(pgn, white_id, black_id, winner) VALUES($1, $2, $3, $4) RETURNING *`,
|
||||
[game.pgn || null, game.white?.id || null, game.black?.id || null, game.winner || null]
|
||||
);
|
||||
return {
|
||||
id: res.rows[0].id,
|
||||
pgn: res.rows[0].pgn,
|
||||
white: { id: res.rows[0].white_id },
|
||||
black: { id: res.rows[0].black_id },
|
||||
winner: res.rows[0].winner
|
||||
} as Game;
|
||||
} catch (err: unknown) {
|
||||
console.log(err);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const find = async (where?: string, limit = 1) => {
|
||||
const query = where
|
||||
? `SELECT * FROM "game"`
|
||||
: {
|
||||
text: `SELECT * FROM "game" WHERE $1 LIMIT $2`,
|
||||
values: [where, limit]
|
||||
};
|
||||
|
||||
try {
|
||||
const res = await db.query(query);
|
||||
return res.rows.map((r) => {
|
||||
return {
|
||||
id: r.id,
|
||||
pgn: r.pgn,
|
||||
white: { id: r.white_id },
|
||||
black: { id: r.black_id },
|
||||
winner: r.winner
|
||||
} as Game;
|
||||
});
|
||||
} catch (err: unknown) {
|
||||
console.log(err);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const update = async (id: number, data: string) => {
|
||||
try {
|
||||
const res = await db.query(`UPDATE "game" SET $1 WHERE id = $2 RETURNING *`, [data, id]);
|
||||
return {
|
||||
id: res.rows[0].id,
|
||||
pgn: res.rows[0].pgn,
|
||||
white: { id: res.rows[0].white_id },
|
||||
black: { id: res.rows[0].black_id },
|
||||
winner: res.rows[0].winner
|
||||
} as Game;
|
||||
} catch (err: unknown) {
|
||||
console.log(err);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const remove = async (id: number) => {
|
||||
try {
|
||||
const res = await db.query(`DELETE FROM "game" WHERE id = $1 RETURNING *`, [id]);
|
||||
return {
|
||||
id: res.rows[0].id,
|
||||
pgn: res.rows[0].pgn,
|
||||
white: { id: res.rows[0].white_id },
|
||||
black: { id: res.rows[0].black_id },
|
||||
winner: res.rows[0].winner
|
||||
} as Game;
|
||||
} catch (err: unknown) {
|
||||
console.log(err);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
export const GameModel = {
|
||||
create,
|
||||
find,
|
||||
update,
|
||||
remove
|
||||
};
|
||||
87
server/src/db/models/user.model.ts
Normal file
87
server/src/db/models/user.model.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
import { db } from "..";
|
||||
import type { User } from "@types";
|
||||
|
||||
const create = async (user: User, password: string) => {
|
||||
if (user.name === "Guest" || user.email === undefined) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await db.query(
|
||||
`INSERT INTO "user"(name, email, password) VALUES($1, $2, $3) RETURNING id, name, email`,
|
||||
[user.name, user.email ?? null, password]
|
||||
);
|
||||
return res.rows[0] as User;
|
||||
} catch (err: unknown) {
|
||||
console.log(err);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const find = async (where?: string, limit = 1) => {
|
||||
// if user is not specified, get all users
|
||||
if (!where) {
|
||||
try {
|
||||
const res = await db.query(`SELECT id, name, email FROM "user"`);
|
||||
return res.rows as Array<User>;
|
||||
} catch (err: unknown) {
|
||||
console.log(err);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
/* const res = await db.query(
|
||||
`SELECT id, name, email FROM "user" WHERE ${typeof user.id === "number" ? "id" : typeof user.name === "string" ? "name" : "email" } = $1 LIMIT $2`,
|
||||
[typeof user.id === "number" ? user.id : typeof user.name === "string" ? user.name : user.email, limit]
|
||||
); */
|
||||
const res = await db.query(`SELECT id, name, email FROM "user" WHERE $1 LIMIT $2`, [
|
||||
where,
|
||||
limit
|
||||
]);
|
||||
return res.rows as Array<User>;
|
||||
} catch (err: unknown) {
|
||||
console.log(err);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const update = async (id: number, data: string) => {
|
||||
if (typeof id === "string" || id === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await db.query(`UPDATE "user" SET $1 WHERE id = $2 RETURNING id, name, email`, [
|
||||
data,
|
||||
id
|
||||
]);
|
||||
return res.rows[0] as User;
|
||||
} catch (err: unknown) {
|
||||
console.log(err);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const remove = async (id: number) => {
|
||||
if (typeof id === "string" || id === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const res = await db.query(`DELETE FROM "user" WHERE id = $1 RETURNING id, name, email`, [
|
||||
id
|
||||
]);
|
||||
return res.rows[0] as User;
|
||||
} catch (err: unknown) {
|
||||
console.log(err);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
export const UserModel = {
|
||||
create,
|
||||
find,
|
||||
update,
|
||||
remove
|
||||
};
|
||||
0
server/src/middleware/error.ts
Normal file
0
server/src/middleware/error.ts
Normal file
42
server/src/middleware/session.ts
Normal file
42
server/src/middleware/session.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { nanoid } from "nanoid";
|
||||
|
||||
import session, { Session } from "express-session";
|
||||
import PGSimple from "connect-pg-simple";
|
||||
import { db } from "../db";
|
||||
const PGSession = PGSimple(session);
|
||||
|
||||
import type { User } from "@types";
|
||||
declare module "express-session" {
|
||||
interface SessionData {
|
||||
user: User;
|
||||
}
|
||||
}
|
||||
declare module "http" {
|
||||
interface IncomingMessage {
|
||||
session: Session & {
|
||||
user: User;
|
||||
};
|
||||
}
|
||||
}
|
||||
const sessionMiddleware = session({
|
||||
store: new PGSession({
|
||||
pool: db,
|
||||
createTableIfMissing: true
|
||||
}),
|
||||
secret: process.env.SESSION_SECRET || "whatever this is",
|
||||
resave: false,
|
||||
saveUninitialized: false,
|
||||
name: "chessu",
|
||||
proxy: true,
|
||||
cookie: {
|
||||
maxAge: 30 * 24 * 60 * 60 * 1000, // 30 days
|
||||
secure: true,
|
||||
httpOnly: true,
|
||||
sameSite: "none"
|
||||
},
|
||||
genid: function () {
|
||||
return nanoid(21);
|
||||
}
|
||||
});
|
||||
|
||||
export default sessionMiddleware;
|
||||
16
server/src/routes/auth.route.ts
Normal file
16
server/src/routes/auth.route.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { Router } from "express";
|
||||
const router = Router();
|
||||
|
||||
import * as controller from "../controllers/auth.controller";
|
||||
|
||||
router.route("/").get(controller.getCurrentSession);
|
||||
|
||||
// create or update guest sessions
|
||||
router.route("/guest").post(controller.guestSession);
|
||||
|
||||
router.route("/logout").post(controller.logoutSession);
|
||||
|
||||
//router.route("/register").post(controller.registerUser);
|
||||
//router.route("/login").post(controller.loginUser);
|
||||
|
||||
export default router;
|
||||
12
server/src/routes/games.route.ts
Normal file
12
server/src/routes/games.route.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { Router } from "express";
|
||||
const router = Router();
|
||||
|
||||
import * as controller from "../controllers/games.controller";
|
||||
|
||||
router.route("/").get(controller.getActiveGames).post(controller.createGame);
|
||||
|
||||
//router.route("/:id").put(controller.joinGame);
|
||||
|
||||
// todo: api for updating games/moves requiring authentication
|
||||
|
||||
export default router;
|
||||
10
server/src/routes/index.ts
Normal file
10
server/src/routes/index.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Router } from "express";
|
||||
const router = Router();
|
||||
|
||||
import games from "./games.route";
|
||||
import auth from "./auth.route";
|
||||
|
||||
router.use("/games", games);
|
||||
router.use("/auth", auth);
|
||||
|
||||
export default router;
|
||||
46
server/src/server.ts
Normal file
46
server/src/server.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import "dotenv/config";
|
||||
import cors from "cors";
|
||||
const corsConfig = { origin: "https://ches.su", credentials: true };
|
||||
|
||||
import express, { Request, Response, NextFunction } from "express";
|
||||
import { createServer } from "http";
|
||||
import session from "./middleware/session";
|
||||
import { Server } from "socket.io";
|
||||
import { init as initSocket } from "./socket";
|
||||
import { db } from "./db";
|
||||
|
||||
import routes from "./routes";
|
||||
|
||||
const app = express();
|
||||
const server = createServer(app);
|
||||
|
||||
// database
|
||||
db.connect();
|
||||
|
||||
// middleware
|
||||
app.use(cors(corsConfig));
|
||||
app.use(express.json());
|
||||
app.set("trust proxy", 1);
|
||||
app.use(session);
|
||||
app.use("/v1", routes);
|
||||
|
||||
// socket.io
|
||||
export const io = new Server(server, { cors: corsConfig });
|
||||
io.use((socket, next) => {
|
||||
session(socket.request as Request, {} as Response, next as NextFunction);
|
||||
});
|
||||
io.use((socket, next) => {
|
||||
const session = socket.request.session;
|
||||
if (session && session.user) {
|
||||
next();
|
||||
} else {
|
||||
console.log("io.use: no session");
|
||||
socket.disconnect();
|
||||
}
|
||||
});
|
||||
initSocket();
|
||||
|
||||
const port = process.env.PORT || 5432;
|
||||
server.listen(port, () => {
|
||||
console.log(`listening on :${port}`);
|
||||
});
|
||||
164
server/src/socket/game.socket.ts
Normal file
164
server/src/socket/game.socket.ts
Normal file
@@ -0,0 +1,164 @@
|
||||
import { activeGames } from "../db/models/game.model";
|
||||
import type { Socket } from "socket.io";
|
||||
import { Chess } from "chess.js";
|
||||
import { io } from "../server";
|
||||
|
||||
export async function joinLobby(this: Socket, gameCode: string) {
|
||||
const game = activeGames.find((g) => g.code === gameCode);
|
||||
if (!game) {
|
||||
console.log(`joinLobby: Game code ${gameCode} not found.`);
|
||||
return;
|
||||
}
|
||||
if (
|
||||
!(game.white?.id === this.request.session.id || game.black?.id === this.request.session.id)
|
||||
) {
|
||||
if (game.observers === undefined) game.observers = [];
|
||||
game.observers?.push(this.request.session.user);
|
||||
}
|
||||
|
||||
if (this.rooms.size >= 2) {
|
||||
await leaveLobby.call(this);
|
||||
}
|
||||
|
||||
await this.join(gameCode);
|
||||
this.emit("receivedLatestGame", game);
|
||||
io.to(game.code as string).emit("receivedLatestLobby", game);
|
||||
io.to(game.code as string).emit("userJoined", this.request.session.user.name);
|
||||
}
|
||||
|
||||
export async function leaveLobby(this: Socket, code?: string) {
|
||||
if (this.rooms.size === 2) {
|
||||
const game = activeGames.find((g) => g.code === (code || Array.from(this.rooms)[1]));
|
||||
if (game) {
|
||||
const user = game.observers?.find((o) => o.id === this.request.session.id);
|
||||
let name = "";
|
||||
if (user) {
|
||||
name = user.name as string;
|
||||
game.observers?.splice(game.observers?.indexOf(user), 1);
|
||||
}
|
||||
if (game.black?.id === this.request.session.id) {
|
||||
name = game.black?.name as string;
|
||||
game.black = undefined;
|
||||
}
|
||||
if (game.white?.id === this.request.session.id) {
|
||||
name = game.white?.name as string;
|
||||
game.white = undefined;
|
||||
}
|
||||
|
||||
if (!game.white && !game.black && !game.observers) {
|
||||
// TODO
|
||||
//activeGames.splice(activeGames.indexOf(game), 1); // remove game if empty
|
||||
} else {
|
||||
this.to(game.code as string).emit("userLeft", name);
|
||||
this.to(game.code as string).emit("receivedLatestLobby", game);
|
||||
}
|
||||
}
|
||||
await this.leave(code || Array.from(this.rooms)[1]);
|
||||
} else if (this.rooms.size >= 3) {
|
||||
console.log(`[WARNING] leaveLobby: room size is ${this.rooms.size}, aborting...`);
|
||||
} else {
|
||||
// try to find a game with this user
|
||||
const game = activeGames.find(
|
||||
(g) =>
|
||||
g.code === code ||
|
||||
g.black?.id === this.request.session.id ||
|
||||
g.white?.id === this.request.session.id ||
|
||||
g.observers?.find((o) => this.request.session.id === o.id)
|
||||
);
|
||||
if (game) {
|
||||
const user = game.observers?.find((o) => this.request.session.id === o.id);
|
||||
let name = "";
|
||||
if (user) {
|
||||
name = user.name as string;
|
||||
game.observers?.splice(game.observers?.indexOf(user), 1);
|
||||
}
|
||||
if (game.black?.id === this.request.session.id) {
|
||||
name = game.black?.name as string;
|
||||
game.black = undefined;
|
||||
}
|
||||
if (game.white?.id === this.request.session.id) {
|
||||
name = game.white?.name as string;
|
||||
game.white = undefined;
|
||||
}
|
||||
this.to(game.code as string).emit("userLeft", name);
|
||||
this.to(game.code as string).emit("receivedLatestLobby", game);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function getLatestGame(this: Socket) {
|
||||
const game = activeGames.find((g) => g.code === Array.from(this.rooms)[1]);
|
||||
if (game) this.emit("receivedLatestGame", game);
|
||||
}
|
||||
|
||||
export async function sendMove(this: Socket, m: { from: string; to: string; promotion?: string }) {
|
||||
const game = activeGames.find((g) => g.code === Array.from(this.rooms)[1]);
|
||||
if (!game) return;
|
||||
const chess = new Chess();
|
||||
if (game.pgn) {
|
||||
chess.loadPgn(game.pgn);
|
||||
}
|
||||
const prevTurn = chess.turn();
|
||||
const newMove = chess.move(m);
|
||||
if (chess.isGameOver()) {
|
||||
let reason = "";
|
||||
if (chess.isCheckmate()) reason = "checkmate";
|
||||
else if (chess.isStalemate()) reason = "stalemate";
|
||||
else if (chess.isThreefoldRepetition()) reason = "repetition";
|
||||
else if (chess.isInsufficientMaterial()) reason = "insufficient";
|
||||
else if (chess.isDraw()) reason = "draw";
|
||||
|
||||
const winnerSide =
|
||||
reason === "checkmate" ? (prevTurn === "w" ? "white" : "black") : undefined;
|
||||
const winnerName =
|
||||
reason === "checkmate"
|
||||
? winnerSide === "white"
|
||||
? game.white?.name
|
||||
: game.black?.name
|
||||
: undefined;
|
||||
if (reason === "checkmate") {
|
||||
game.winner = winnerSide;
|
||||
} else {
|
||||
game.winner = "draw";
|
||||
}
|
||||
io.to(game.code as string).emit("gameOver", { reason, winnerName, winnerSide });
|
||||
}
|
||||
if (newMove === null) {
|
||||
this.emit("receivedLatestGame", game);
|
||||
} else {
|
||||
game.pgn = chess.pgn();
|
||||
this.to(game.code as string).emit("receivedMove", { from: m.from, to: m.to });
|
||||
}
|
||||
}
|
||||
|
||||
export async function joinAsPlayer(this: Socket) {
|
||||
const game = activeGames.find((g) => g.code === Array.from(this.rooms)[1]);
|
||||
if (!game) return;
|
||||
const user = game.observers?.find((o) => o.id === this.request.session.id);
|
||||
if (!game.white) {
|
||||
game.white = this.request.session.user;
|
||||
if (user) game.observers?.splice(game.observers?.indexOf(user), 1);
|
||||
io.to(game.code as string).emit("userJoinedAsPlayer", {
|
||||
name: this.request.session.user.name,
|
||||
side: "white"
|
||||
});
|
||||
} else if (!game.black) {
|
||||
game.black = this.request.session.user;
|
||||
if (user) game.observers?.splice(game.observers?.indexOf(user), 1);
|
||||
io.to(game.code as string).emit("userJoinedAsPlayer", {
|
||||
name: this.request.session.user.name,
|
||||
side: "black"
|
||||
});
|
||||
} else {
|
||||
console.log("[WARNING] attempted to join a game with already 2 players");
|
||||
}
|
||||
io.to(game.code as string).emit("receivedLatestGame", game);
|
||||
io.to(game.code as string).emit("receivedLatestLobby", game);
|
||||
}
|
||||
|
||||
export async function chat(this: Socket, message: string) {
|
||||
this.to(Array.from(this.rooms)[1]).emit("chat", {
|
||||
author: this.request.session.user,
|
||||
message
|
||||
});
|
||||
}
|
||||
34
server/src/socket/index.ts
Normal file
34
server/src/socket/index.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import type { Socket } from "socket.io";
|
||||
import { io } from "../server";
|
||||
import { joinLobby, leaveLobby, getLatestGame, sendMove, joinAsPlayer, chat } from "./game.socket";
|
||||
|
||||
const socketConnect = (socket: Socket) => {
|
||||
const req = socket.request;
|
||||
|
||||
// re-analyze if this is necessary, or if io.use will handle logout
|
||||
socket.use((__, next) => {
|
||||
req.session.reload((err) => {
|
||||
if (err) {
|
||||
console.log("reload: disconnecting socket.");
|
||||
console.log(err);
|
||||
socket.disconnect();
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
socket.on("disconnect", leaveLobby);
|
||||
|
||||
socket.on("joinLobby", joinLobby);
|
||||
socket.on("leaveLobby", leaveLobby);
|
||||
|
||||
socket.on("getLatestGame", getLatestGame);
|
||||
socket.on("sendMove", sendMove);
|
||||
socket.on("joinAsPlayer", joinAsPlayer);
|
||||
socket.on("chat", chat);
|
||||
};
|
||||
|
||||
export const init = () => {
|
||||
io.on("connection", socketConnect);
|
||||
};
|
||||
14
server/tsconfig.json
Normal file
14
server/tsconfig.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2021",
|
||||
"module": "commonjs",
|
||||
"paths": {
|
||||
"@types": ["../types/"]
|
||||
},
|
||||
"outDir": "./dist",
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"skipLibCheck": true
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user