This content originally appeared on DEV Community and was authored by YogeshTogeshZ YT
I have a stackblitz project, and when i go to the .stackblitz.io site, it either shows {} (when im using port 3000) or its stuck at 95% loading before starting the project(when im using port 0.0.0.0) i am using a server in this project, but the same 95% load problem serverless. how am i supposed to fix this. This is my server.js, if you want any other scripts i can try telling you them. very unfinished script i tried asking ai for help but it didnt fix anything, just spammed comments which i didnt ask for I HAVE NO IDEA WHY. This is my first post in dev.to, please dont get angry if i do something wrong.
// server.js (Complete, Functional Script)
const express = require('express');
const http = require('http');
const { Server } = require('socket.io');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
const app = express();
const server = http.createServer(app);
const io = new Server(server, {
cors: {
origin: '*',
methods: ['GET', 'POST'],
},
transports: ['websocket', 'polling'],
});
// --- Configuration and Constants ---
const PORT = process.env.PORT || 3000;
const JWT_SECRET = 'your_super_secret_key'; // CHANGE THIS IN PRODUCTION!
const PLAYER_SPEED = 5;
const GAME_TICK_RATE = 1000 / 60; // 60 updates per second
// --- Data Storage (In-Memory Mock Database) ---
let users = []; // Stores account data: { id, username, passwordHash }
let players = {}; // Stores active game data: { socketId: { id, userId, username, x, y, input } }
// --- Helper Functions ---
function getPlayerUser(socketId) {
const player = players[socketId];
if (player && player.userId) {
return users.find((u) => u.id === player.userId);
}
return null;
}
function findUserById(userId) {
return users.find((u) => u.id === userId);
}
function findUserByUsername(username) {
return users.find((u) => u.username.toLowerCase() === username.toLowerCase());
}
/**
* Deletes a user from the 'database'.
* @param {string} userId - The ID of the user to delete.
* @returns {boolean} True if deletion was successful, false otherwise.
*/
function deleteUser(userId) {
const initialLength = users.length;
users = users.filter((u) => u.id !== userId);
return users.length < initialLength;
}
// --- Player Initialization and Logic ---
function createNewPlayer(socketId, username, userId = null) {
// Check if player already exists (reconnection case)
if (players[socketId]) {
players[socketId].userId = userId;
players[socketId].username = username;
return players[socketId];
}
// Create new player
players[socketId] = {
id: socketId,
userId: userId, // Link to the registered user ID if logged in
username: username,
x: Math.random() * 800 + 100, // Spawn in a random spot
y: Math.random() * 600 + 100,
input: { up: false, down: false, left: false, right: false },
};
return players[socketId];
}
// --- Core Game Loop ---
function gameLoop() {
for (const id in players) {
const player = players[id];
// Apply movement based on input
if (player.input.up) player.y -= PLAYER_SPEED;
if (player.input.down) player.y += PLAYER_SPEED;
if (player.input.left) player.x -= PLAYER_SPEED;
if (player.input.right) player.x += PLAYER_SPEED;
// Keep player in bounds (simple bounds check)
player.x = Math.max(0, Math.min(1920, player.x));
player.y = Math.max(0, Math.min(1080, player.y));
}
// Send the updated state to all connected clients
io.emit('gameStateUpdate', players);
}
// Start the game loop
setInterval(gameLoop, GAME_TICK_RATE);
// --- Express Setup ---
app.use(express.json());
app.use(express.static('public'));
app.get('/', (req, res) => {
res.setHeader('Content-Type', 'text/html');
res.sendFile(__dirname + '/public/index.html');
});
// FIX: Remove the problematic app.get('*') and rely on express.static to handle files.
// The wildcard route conflicted with internal Socket.IO routes and caused the error.
// --- Socket.IO Connection and Handlers ---
io.use((socket, next) => {
const token = socket.handshake.auth.token;
if (token) {
try {
const decoded = jwt.verify(token, JWT_SECRET);
socket.data.userId = decoded.id;
} catch (err) {
console.log(
`[AUTH] Invalid token for socket ${socket.id}. Connecting as guest.`
);
}
}
next();
});
io.on('connection', (socket) => {
console.log(`[CONNECT] A user connected: ${socket.id}`);
let user = null;
let username = 'Guest';
// Check for authenticated user from handshake token
if (socket.data.userId) {
user = findUserById(socket.data.userId);
if (user) {
username = user.username;
} else {
// User ID in token is valid but doesn't exist (deleted account case)
socket.emit('auth:revoked');
delete socket.data.userId;
}
}
// 1. Initialize the new player object
const newPlayer = createNewPlayer(socket.id, username, user ? user.id : null);
// 2. Notify the connecting client of their setup (CRITICAL for client UI/Player draw)
socket.emit('playerSetup', {
playerId: socket.id,
initialPlayers: players, // Send the full initial state
});
// 3. Notify existing clients about the new player
socket.broadcast.emit('newPlayer', newPlayer);
// --- Authentication Handlers ---
socket.on('account:register', async ({ username, password }, callback) => {
const usernameTrimmed = username.trim();
if (findUserByUsername(usernameTrimmed)) {
return callback({ success: false, message: 'Username already taken.' });
}
const id = Date.now().toString(); // Simple unique ID
const passwordHash = await bcrypt.hash(password, 10);
user = { id, username: usernameTrimmed, passwordHash };
users.push(user);
const token = jwt.sign({ id: user.id }, JWT_SECRET, { expiresIn: '7d' });
// Update player data on successful registration
const player = players[socket.id];
if (player) {
player.userId = user.id;
player.username = user.username;
}
console.log(`[AUTH] New user registered: ${user.username}`);
io.emit('gameStateUpdate', players); // Update all clients with new username
callback({ success: true, token });
});
socket.on('account:login', async ({ username, password }, callback) => {
user = findUserByUsername(username);
if (!user || !(await bcrypt.compare(password, user.passwordHash))) {
return callback({
success: false,
message: 'Invalid username or password.',
});
}
const token = jwt.sign({ id: user.id }, JWT_SECRET, { expiresIn: '7d' });
// Update player data on successful login
const player = players[socket.id];
if (player) {
player.userId = user.id;
player.username = user.username;
}
console.log(`[AUTH] User logged in: ${user.username}`);
io.emit('gameStateUpdate', players); // Update all clients with logged-in username
callback({ success: true, token });
});
// Handle Account Deletion (Permadelete)
socket.on('account:delete', async (data, callback) => {
// 1. Authorization check
user = getPlayerUser(socket.id);
if (!user || !user.id) {
return callback({
success: false,
message: 'Authentication required to delete account.',
});
}
const usernameToDelete = user.username;
const userIdToDelete = user.id;
// 2. Delete the user from the database
const deletionSuccessful = deleteUser(userIdToDelete);
if (deletionSuccessful) {
// 3. Clean up server state for the game player
delete players[socket.id];
// 4. Notify client of success *before* disconnecting
callback({ success: true });
// 5. Notify all other clients of the player's departure
io.emit('playerDisconnected', socket.id);
// 6. Force client to log out and then disconnect
socket.emit('auth:revoked');
console.log(
`[AUTH] Account for user ${usernameToDelete} has been permanently deleted.`
);
// Disconnect the socket after a brief delay to ensure the events are processed
setTimeout(() => {
socket.disconnect(true);
}, 100);
} else {
callback({
success: false,
message: 'Failed to find and delete account data.',
});
}
});
// --- Game Handlers ---
socket.on('playerInput', (input) => {
const player = players[socket.id];
if (player) {
player.input = input;
}
});
// --- Disconnect Handler ---
socket.on('disconnect', () => {
console.log(`[DISCONNECT] User disconnected: ${socket.id}`);
delete players[socket.id];
io.emit('playerDisconnected', socket.id);
});
});
// Use '0.0.0.0' for StackBlitz to bind to all network interfaces
server.listen(PORT, '0.0.0.0', () => {
console.log(`Server running on port ${PORT}`);
});
This content originally appeared on DEV Community and was authored by YogeshTogeshZ YT