import fs from "fs"; import path from "path"; import express, {Application} from 'express'; import {createServer as httpServer} from 'http'; import {addHttpRoutes} from './app/utilities/Http'; import cors from 'cors'; import {Server as SocketServer} from 'socket.io'; import {TSocket} from "./app/utilities/Types"; import config from './app/utilities/Config'; import prisma from './app/utilities/Prisma'; import ZoneManager from "./app/ZoneManager"; import UserManager from "./app/UserManager"; import {Authentication} from "./app/middleware/Authentication"; import CommandManager from "./app/CommandManager"; import {Dirent} from "node:fs"; export class Server { private readonly app: Application; private readonly http: any; private readonly io: SocketServer; /** * Creates an instance of GameServer. */ constructor() { this.app = express(); this.app.use(cors()); this.app.use(express.json()); this.app.use(express.urlencoded({ extended: true })); this.http = httpServer(this.app) this.io = new SocketServer(this.http); this.io.use(Authentication) } /** * Start the server */ public async start() { // Check prisma connection try { await prisma.$connect(); console.log('[✅] Database connected'); } catch (error: any) { throw new Error(`[❌] Database connection failed: ${error.message}`); } // Start the server try { await this.http.listen(config.PORT, config.HOST); console.log('[✅] Socket.IO running on port', config.PORT); } catch (error: any) { throw new Error(`[❌] Socket.IO failed to start: ${error.message}`); } // Add http API routes await addHttpRoutes(this.app); // Load user manager await UserManager.boot(); // Load zone manager await ZoneManager.boot(); // Load command manager // await CommandManager.boot(this.io); // Listen for socket connections this.io.on('connection', this.handleConnection.bind(this)); } /** * Handle socket connection * @param socket * @private */ private async handleConnection(socket: TSocket) { const eventsPath = path.join(__dirname, 'app', 'events'); try { await this.loadEventHandlers(eventsPath, socket); } catch (error: any) { throw new Error('[❌] Failed to load event handlers: ' + error.message); } } private async loadEventHandlers(dir: string, socket: TSocket) { const files: Dirent[] = await fs.promises.readdir(dir, { withFileTypes: true }); for (const file of files) { const fullPath = path.join(dir, file.name); if (file.isDirectory()) { await this.loadEventHandlers(fullPath, socket); } else if (file.isFile()) { const module = await import(fullPath); module.default(socket, this.io); } } } } // Start the server const server = new Server(); server.start();