DEV Community

YogeshTogeshZ YT
YogeshTogeshZ YT

Posted on

StackBlitz website not loading

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}`);
});

Enter fullscreen mode Exit fullscreen mode

Top comments (0)