Commit 857a1a59 authored by Vũ Gia Vương's avatar Vũ Gia Vương

Merge branch 'backup'

parents ce1d7942 9638dab2
......@@ -6,6 +6,7 @@
/temp/
/local/
/build/
package-lock.json
node_modules/
# dist/
......
......@@ -5,7 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
Object.defineProperty(exports, "__esModule", { value: true });
const v2_1 = __importDefault(require("./v2"));
class User {
constructor(token, id) {
constructor(user) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
this.id = '';
this.token = '';
this.towerNumber = 0;
......@@ -21,9 +22,21 @@ class User {
this.timeStart = 0;
this.isStartGame = true;
this.history = [];
this.token = token;
this.id = id;
this.reset();
this.token = user.token;
this.id = user.id;
this.towerNumber = user.towerNumber || 0;
this.direction = user.direction || 1;
this.distance2Tower = user.distance2Tower || 0;
this.score = user.score || 0;
this.totalScore = user.totalScore || 0;
this.combo = user.combo || 0;
this.timeStart = user.timeStart || 0;
this.isStartGame = user.isStartGame || true;
this.history = ((_a = user.history) === null || _a === void 0 ? void 0 : _a.map(h => new History(h.timeStart, h.timePlayed, h.totalScore, h.tower, h.score))) || [];
this.curBlock = new v2_1.default(((_b = user.curBlock) === null || _b === void 0 ? void 0 : _b.x) || 0, ((_c = user.curBlock) === null || _c === void 0 ? void 0 : _c.y) || 0);
this.nextBlock = new v2_1.default(((_d = user.nextBlock) === null || _d === void 0 ? void 0 : _d.x) || 0, ((_e = user.nextBlock) === null || _e === void 0 ? void 0 : _e.y) || 0);
this.screenPos = new v2_1.default(((_f = user.screenPos) === null || _f === void 0 ? void 0 : _f.x) || 0, ((_g = user.screenPos) === null || _g === void 0 ? void 0 : _g.y) || 0);
this.position = new v2_1.default(((_h = user.position) === null || _h === void 0 ? void 0 : _h.x) || 0, ((_j = user.position) === null || _j === void 0 ? void 0 : _j.y) || 0);
}
reset() {
this.score = 0;
......@@ -46,12 +59,17 @@ class User {
}
}
class History {
constructor() {
constructor(timeStart, timePlayed, totalScore, tower, score) {
this.timeStart = 0;
this.timePlayed = 0;
this.totalScore = 0;
this.tower = 0;
this.score = 0;
this.timeStart = timeStart;
this.timePlayed = timePlayed;
this.totalScore = totalScore;
this.tower = tower;
this.score = score;
}
}
exports.default = User;
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.redis = void 0;
const server_1 = __importDefault(require("./server"));
const http_1 = __importDefault(require("http"));
const socket_io_1 = require("socket.io");
const socket_1 = require("./socket");
const PORT = 3001;
const redis_adapter_1 = require("@socket.io/redis-adapter");
const redis_1 = require("redis");
const PORT = process.env.PORT || 6636;
const REDIS_URL = "redis://default:Myreview123@123a@127.0.0.1:6379";
// const REDIS_URL = "redis://127.0.0.1:6379";
const PATH = '/socketws/socket.io';
exports.redis = (0, redis_1.createClient)({ url: REDIS_URL });
function initRedis() {
return __awaiter(this, void 0, void 0, function* () {
yield exports.redis.connect();
console.log("✅ Redis connected");
});
}
initRedis().catch(err => {
console.error("Redis error:", err);
});
const server = http_1.default.createServer(server_1.default);
const io = new socket_io_1.Server(server, {
path: '/socket/socket.io',
path: PATH,
cors: {
methods: ["GET", "POST"],
origin: "*"
}
});
const pubClient = (0, redis_1.createClient)({ url: REDIS_URL });
const subClient = pubClient.duplicate();
Promise.all([pubClient.connect(), subClient.connect()]).then(() => {
io.adapter((0, redis_adapter_1.createAdapter)(pubClient, subClient));
console.log("✅ Socket.IO Redis adapter connected");
});
(0, socket_1.setupSocket)(io);
server.listen(PORT, () => {
console.log(`Server is running on port ${PORT}!`);
......
......@@ -11,7 +11,7 @@ app.use(express_1.default.json());
app.get('/', (req, res, next) => {
res.send('Hello World');
});
// app.get('/socket', (req: Request, res: Response, next: NextFunction) => {
// res.send('socket')
// })
app.get('/socketws/dev', (req, res, next) => {
res.send('dev');
});
exports.default = app;
......@@ -16,6 +16,7 @@ exports.setupSocket = setupSocket;
const User_1 = __importDefault(require("./Model/User"));
const v2_1 = __importDefault(require("./Model/v2"));
const networkCtrl_1 = require("./Controller/networkCtrl");
const _1 = require(".");
const users = new Map();
const Y_RADIO = 0.5560472;
const HALF_SIZE_TOWER = 56.43580423808985;
......@@ -36,36 +37,52 @@ const CONFIG = {
REQUEST_HISTORY: '603',
}
};
const TIME_EX = 24 * 60 * 60;
function setupSocket(io) {
return __awaiter(this, void 0, void 0, function* () {
io.use((socket, next) => __awaiter(this, void 0, void 0, function* () {
try {
io.use((socket, next) => {
const token = String(socket.handshake.query.token);
const userId = String(socket.handshake.query.userId);
if (!token || !userId) {
return;
}
if (!users.has(userId)) {
users.set(userId, new User_1.default(token, userId));
// const keys = await redis.keys("user:*");
// console.log('keys', keys)
const userJson = yield _1.redis.get(`user:${userId}`);
const user = userJson ? JSON.parse(userJson) : null;
const newUser = new User_1.default(user || { token, id: userId });
users.set(userId, newUser);
if (!user) {
yield _1.redis.set(`user:${userId}`, JSON.stringify(user));
yield _1.redis.expire(`user:${userId}`, TIME_EX);
}
next();
});
}
catch (error) {
console.log('error', error);
}
}));
io.on("connection", (socket) => {
try {
console.log(`🟢 Client connected: ${socket.id}`);
socket.on(CONFIG.EVT.START_GAME, (data) => startGame(socket, data));
socket.on(CONFIG.EVT.PASS_TOWER, (data) => __awaiter(this, void 0, void 0, function* () { return yield passTower(socket, data); }));
socket.on(CONFIG.EVT.HISTORY, () => __awaiter(this, void 0, void 0, function* () { return getHistory(socket); }));
socket.on(CONFIG.EVT.END_GAME, () => endGame(socket));
socket.on("disconnect", () => onDisconnect(socket));
});
const userId = String(socket.handshake.query.userId);
const user = users.get(userId);
socket.on(CONFIG.EVT.START_GAME, (data) => startGame(socket, data, user));
socket.on(CONFIG.EVT.PASS_TOWER, (data) => __awaiter(this, void 0, void 0, function* () { return yield passTower(socket, data, user); }));
socket.on(CONFIG.EVT.HISTORY, () => __awaiter(this, void 0, void 0, function* () { return yield getHistory(socket, user); }));
socket.on(CONFIG.EVT.END_GAME, () => endGame(socket, user));
socket.on("disconnect", () => __awaiter(this, void 0, void 0, function* () { return yield onDisconnect(socket, user); }));
}
catch (error) {
console.log('error', error);
}
});
});
}
function endGame(socket) {
function endGame(socket, user) {
return __awaiter(this, void 0, void 0, function* () {
try {
const user = getUserBySocket(socket);
yield (0, networkCtrl_1.endGameApi)(user);
user.reset();
}
......@@ -74,20 +91,27 @@ function endGame(socket) {
}
});
}
function onDisconnect(socket) {
function onDisconnect(socket, user) {
return __awaiter(this, void 0, void 0, function* () {
try {
console.log(`🔴 Client disconnected: ${socket.id}`);
// endGame(socket);
yield _1.redis.set(`user:${user.id}`, JSON.stringify(user));
yield _1.redis.expire(`user:${user.id}`, TIME_EX);
users.delete(user.id);
}
catch (error) {
console.log('error', error);
}
});
}
function getHistory(socket) {
function getHistory(socket, user) {
return __awaiter(this, void 0, void 0, function* () {
const user = getUserBySocket(socket);
socket.emit(CONFIG.EVT.REQUEST_HISTORY, user.history);
});
}
function startGame(socket, data) {
function startGame(socket, data, user) {
return __awaiter(this, void 0, void 0, function* () {
try {
const user = getUserBySocket(socket);
const result = yield (0, networkCtrl_1.startGameApi)(data);
if (result && user.isStartGame) {
user.reset();
......@@ -95,7 +119,7 @@ function startGame(socket, data) {
if (result) {
socket.emit(CONFIG.EVT.REQUEST_START_GAME, true);
user.isStartGame = true;
addBlock(socket);
addBlock(socket, user);
}
else {
console.log('start game fail');
......@@ -107,10 +131,9 @@ function startGame(socket, data) {
}
});
}
function passTower(socket, data) {
function passTower(socket, data, user) {
return __awaiter(this, void 0, void 0, function* () {
try {
const user = getUserBySocket(socket);
let xDistance_ = 0;
const { direction, nextBlock, towerNumber, position } = user;
if (towerNumber > MAX_TOWER) {
......@@ -155,7 +178,7 @@ function passTower(socket, data) {
else {
user.combo = 0;
}
user.totalScore += score;
user.totalScore += Math.max(score, 0);
const dataSocket = {
target,
score,
......@@ -174,7 +197,7 @@ function passTower(socket, data) {
user.position = target;
socket.emit(CONFIG.EVT.REQUEST_PASS_TOWER, dataSocket);
if (score > 0) {
addBlock(socket);
addBlock(socket, user);
}
else {
socket.emit(CONFIG.EVT.REQUEST_HISTORY, user.history);
......@@ -187,10 +210,9 @@ function passTower(socket, data) {
}
});
}
function addBlock(socket) {
function addBlock(socket, user) {
return __awaiter(this, void 0, void 0, function* () {
try {
const user = getUserBySocket(socket);
const towerNumber = ++user.towerNumber;
const xDistance = ((Math.min(towerNumber, 100) / 100 + 1) + Math.random() * (towerNumber <= 10 ? 0.5 : 1)) * 150;
const yDistance = xDistance * Y_RADIO;
......@@ -201,12 +223,9 @@ function addBlock(socket) {
user.nextBlock.x = user.curBlock.x + (xDistance * user.direction);
user.nextBlock.y = user.curBlock.y + yDistance;
user.distance2Tower = user.nextBlock.distanceTo(user.curBlock);
user.screenPos = user.nextBlock.add(user.curBlock).mul(0.5).sub(new v2_1.default(0, 100));
const data = {
nextBlock: user.nextBlock,
screenPos: user.screenPos,
direction: user.direction,
distance2Tower: user.distance2Tower,
towerNumber: user.towerNumber,
};
user.timeStart = Date.now();
......@@ -217,7 +236,3 @@ function addBlock(socket) {
}
});
}
function getUserBySocket(socket) {
const userId = String(socket.handshake.query.userId);
return users.get(userId);
}
// ecosystem.config.js
module.exports = {
apps: [
{
name: "flip-jump",
script: "dist/index.js",
instances: "max",
exec_mode: "cluster",
sticky: true
}
]
};
This diff is collapsed.
......@@ -12,12 +12,15 @@
"author": "",
"license": "ISC",
"dependencies": {
"@socket.io/redis-adapter": "^8.3.0",
"@types/express": "^5.0.3",
"cors": "^2.8.5",
"express": "^5.1.0",
"http": "^0.0.1-security",
"nodemon": "^3.1.10",
"redis": "^5.8.1",
"socket.io": "^4.8.1",
"socket.io-redis": "^6.1.1",
"ts-node": "^10.9.2",
"typescript": "^5.9.2"
}
......
......@@ -20,10 +20,25 @@ class User {
public isStartGame: boolean = true;
public history: History[] = [];
constructor(token: string, id: string) {
this.token = token;
this.id = id;
this.reset();
constructor(user: User) {
this.token = user.token;
this.id = user.id;
this.towerNumber = user.towerNumber || 0;
this.direction = user.direction || 1;
this.distance2Tower = user.distance2Tower || 0;
this.score = user.score || 0;
this.totalScore = user.totalScore || 0;
this.combo = user.combo || 0;
this.timeStart = user.timeStart || 0;
this.isStartGame = user.isStartGame || true;
this.history = user.history?.map(h => new History(h.timeStart, h.timePlayed, h.totalScore, h.tower, h.score)) || [];
this.curBlock = new v2(user.curBlock?.x || 0, user.curBlock?.y || 0);
this.nextBlock = new v2(user.nextBlock?.x || 0, user.nextBlock?.y || 0);
this.screenPos = new v2(user.screenPos?.x || 0, user.screenPos?.y || 0);
this.position = new v2(user.position?.x || 0, user.position?.y || 0);
}
public reset() {
......@@ -53,6 +68,14 @@ class History {
public totalScore: number = 0;
public tower: number = 0;
public score: number = 0;
constructor(timeStart: number, timePlayed: number, totalScore: number, tower: number, score: number) {
this.timeStart = timeStart;
this.timePlayed = timePlayed;
this.totalScore = totalScore;
this.tower = tower;
this.score = score;
}
}
export interface IDataPassTower {
......@@ -65,9 +88,7 @@ export interface IDataPassTower {
export interface IDataSpawnTower {
nextBlock: v2,
screenPos: v2,
direction: number,
distance2Tower: number,
towerNumber: number,
}
......
......@@ -2,18 +2,43 @@ import app from "./server";
import http from 'http';
import { Server } from 'socket.io';
import { setupSocket } from "./socket";
import { createAdapter } from "@socket.io/redis-adapter";
import { createClient } from "redis";
const PORT = process.env.PORT || 6636;
const REDIS_URL = "redis://default:Myreview123@123a@127.0.0.1:6379";
// const REDIS_URL = "redis://127.0.0.1:6379";
const PATH = '/socketws/socket.io';
export const redis = createClient({ url: REDIS_URL });
async function initRedis() {
await redis.connect();
console.log("✅ Redis connected");
}
initRedis().catch(err => {
console.error("Redis error:", err);
});
const PORT = 3001;
const server = http.createServer(app);
const io = new Server(server, {
path: '/socket/socket.io',
path: PATH,
cors: {
methods: ["GET", "POST"],
origin: "*"
}
});
const pubClient = createClient({ url: REDIS_URL });
const subClient = pubClient.duplicate();
Promise.all([pubClient.connect(), subClient.connect()]).then(() => {
io.adapter(createAdapter(pubClient, subClient));
console.log("✅ Socket.IO Redis adapter connected");
});
setupSocket(io);
server.listen(PORT, () => {
......
......@@ -9,8 +9,9 @@ app.get('/', (req: Request, res: Response, next: NextFunction) => {
res.send('Hello World')
})
// app.get('/socket', (req: Request, res: Response, next: NextFunction) => {
// res.send('socket')
// })
app.get('/socketws/dev', (req: Request, res: Response, next: NextFunction) => {
res.send('dev')
})
export default app;
......@@ -2,8 +2,10 @@ import { Server, Socket } from "socket.io";
import User, { IDataPassTower, IDataSpawnTower, IRequestPassTower } from "./Model/User";
import v2 from "./Model/v2";
import { endGameApi, startGameApi } from "./Controller/networkCtrl";
import { redis } from ".";
const users: Map<string, User> = new Map<string, User>();
const Y_RADIO: number = 0.5560472;
const HALF_SIZE_TOWER: number = 56.43580423808985;
const INIT_SPEED: number = 300;
......@@ -25,39 +27,58 @@ const CONFIG = {
}
};
export function setupSocket(io: Server) {
const TIME_EX = 24 * 60 * 60;
export async function setupSocket(io: Server) {
io.use(async (socket: Socket, next) => {
try {
io.use((socket: Socket, next) => {
const token = String(socket.handshake.query.token);
const userId = String(socket.handshake.query.userId);
if (!token || !userId) {
return;
}
if (!users.has(userId)) {
users.set(userId, new User(token, userId));
// const keys = await redis.keys("user:*");
// console.log('keys', keys)
const userJson = await redis.get(`user:${userId}`);
const user = userJson ? JSON.parse(userJson) : null;
const newUser = new User(user || { token, id: userId } as User);
users.set(userId, newUser);
if (!user) {
await redis.set(`user:${userId}`, JSON.stringify(user));
await redis.expire(`user:${userId}`, TIME_EX);
}
next();
} catch (error) {
console.log('error', error)
}
});
io.on("connection", (socket: Socket) => {
try {
console.log(`🟢 Client connected: ${socket.id}`);
const userId = String(socket.handshake.query.userId);
const user = users.get(userId)!;
socket.on(CONFIG.EVT.START_GAME, (data: string) => startGame(socket, data));
socket.on(CONFIG.EVT.PASS_TOWER, async (data: IRequestPassTower) => await passTower(socket, data));
socket.on(CONFIG.EVT.HISTORY, async () => getHistory(socket));
socket.on(CONFIG.EVT.START_GAME, (data: string) => startGame(socket, data, user));
socket.on(CONFIG.EVT.PASS_TOWER, async (data: IRequestPassTower) => await passTower(socket, data, user));
socket.on(CONFIG.EVT.HISTORY, async () => await getHistory(socket, user));
socket.on(CONFIG.EVT.END_GAME, () => endGame(socket));
socket.on(CONFIG.EVT.END_GAME, () => endGame(socket, user));
socket.on("disconnect", () => onDisconnect(socket));
});
socket.on("disconnect", async () => await onDisconnect(socket, user));
} catch (error) {
console.log('error', error)
}
});
}
async function endGame(socket: Socket) {
async function endGame(socket: Socket, user: User) {
try {
const user = getUserBySocket(socket);
await endGameApi(user);
user.reset();
} catch (error) {
......@@ -65,19 +86,24 @@ async function endGame(socket: Socket) {
}
}
function onDisconnect(socket: Socket): void {
async function onDisconnect(socket: Socket, user: User) {
try {
console.log(`🔴 Client disconnected: ${socket.id}`)
// endGame(socket);
await redis.set(`user:${user.id}`, JSON.stringify(user));
await redis.expire(`user:${user.id}`, TIME_EX);
users.delete(user.id);
} catch (error) {
console.log('error', error)
}
}
async function getHistory(socket: Socket) {
const user = getUserBySocket(socket);
async function getHistory(socket: Socket, user: User) {
socket.emit(CONFIG.EVT.REQUEST_HISTORY, user.history);
}
async function startGame(socket: Socket, data: any) {
async function startGame(socket: Socket, data: any, user: User) {
try {
const user = getUserBySocket(socket);
const result = await startGameApi(data);
if (result && user.isStartGame) {
......@@ -87,7 +113,7 @@ async function startGame(socket: Socket, data: any) {
if (result) {
socket.emit(CONFIG.EVT.REQUEST_START_GAME, true);
user.isStartGame = true;
addBlock(socket);
addBlock(socket, user);
} else {
console.log('start game fail');
socket.emit(CONFIG.EVT.REQUEST_START_GAME, false);
......@@ -97,9 +123,8 @@ async function startGame(socket: Socket, data: any) {
}
}
async function passTower(socket: Socket, data: IRequestPassTower) {
async function passTower(socket: Socket, data: IRequestPassTower, user: User) {
try {
const user = getUserBySocket(socket);
let xDistance_ = 0;
const { direction, nextBlock, towerNumber, position } = user;
......@@ -152,7 +177,7 @@ async function passTower(socket: Socket, data: IRequestPassTower) {
user.combo = 0;
}
user.totalScore += score;
user.totalScore += Math.max(score, 0);
const dataSocket: IDataPassTower = {
target,
......@@ -176,7 +201,7 @@ async function passTower(socket: Socket, data: IRequestPassTower) {
socket.emit(CONFIG.EVT.REQUEST_PASS_TOWER, dataSocket);
if (score > 0) {
addBlock(socket);
addBlock(socket, user);
} else {
socket.emit(CONFIG.EVT.REQUEST_HISTORY, user.history);
await endGameApi(user);
......@@ -187,9 +212,8 @@ async function passTower(socket: Socket, data: IRequestPassTower) {
}
}
async function addBlock(socket: Socket) {
async function addBlock(socket: Socket, user: User) {
try {
const user = getUserBySocket(socket);
const towerNumber = ++user.towerNumber;
const xDistance = ((Math.min(towerNumber, 100) / 100 + 1) + Math.random() * (towerNumber <= 10 ? 0.5 : 1)) * 150;
......@@ -202,13 +226,10 @@ async function addBlock(socket: Socket) {
user.nextBlock.x = user.curBlock.x + (xDistance * user.direction);
user.nextBlock.y = user.curBlock.y + yDistance;
user.distance2Tower = user.nextBlock.distanceTo(user.curBlock);
user.screenPos = user.nextBlock.add(user.curBlock).mul(0.5).sub(new v2(0, 100));
const data: IDataSpawnTower = {
nextBlock: user.nextBlock,
screenPos: user.screenPos,
direction: user.direction,
distance2Tower: user.distance2Tower,
towerNumber: user.towerNumber,
};
user.timeStart = Date.now();
......@@ -217,8 +238,3 @@ async function addBlock(socket: Socket) {
console.log('error', error)
}
}
\ No newline at end of file
function getUserBySocket(socket: Socket) {
const userId = String(socket.handshake.query.userId);
return users.get(userId)!;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment