Files
wownerogue/index.js
T
2025-04-27 09:03:16 -04:00

286 lines
8.0 KiB
JavaScript

const express = require('express');
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var rpc = require('./rpccalls.js');
var db = require('./dbcalls.js');
var user = require('./user.js');
const Game = require('./game');
const activeGames = new Map(); // Maps socketId to Game objects
let lastBlockHeight = 0; // Track last block height
const MIN_FEE = 10; // Minimum entrance fee in WOW
const MAX_FEE = 100; // Maximum entrance fee in WOW
const WAITING_PLAYERS = []; // Players waiting for the next block
var users = [];
var players = [];
app.use(express.static('html'));
app.get('/', function(req, res) {
res.sendfile('index.html');
});
// Function to get a user by socket ID
function getUserBySocket(socketId) {
return users.find(user => user.socketid === socketId);
}
// Modified block check function
setInterval(function() {
rpc.daemonCall("get_block_count", "", function(result) {
const currentHeight = result.result.count;
rpc.lastBlock.setHeight(currentHeight);
// If new block found
if (currentHeight > lastBlockHeight) {
console.log(`New block found: ${currentHeight}`);
io.emit('blockheight', currentHeight);
// Start games for waiting players
startGamesForWaiting(currentHeight);
// Check active games for timeout
checkGamesTimeout(currentHeight);
lastBlockHeight = currentHeight;
} else {
io.emit('blockheight', currentHeight);
}
});
}, 10000);
// Start games for waiting players
function startGamesForWaiting(blockHeight) {
while (WAITING_PLAYERS.length > 0) {
const userId = WAITING_PLAYERS.shift();
const user = getUserBySocket(userId);
if (user) {
user.blockRec = blockHeight;
const game = user.startGame(80, 40); // Create a new game
activeGames.set(userId, game);
io.to(userId).emit('game_start', {
map: game.dungeon.map,
player: game.player,
monster: game.monster,
entrance: game.dungeon.entrance,
exit: game.dungeon.exit,
treasure: game.dungeon.treasure,
blockHeight: blockHeight
});
}
}
}
// Check if any active games have timed out
function checkGamesTimeout(currentHeight) {
activeGames.forEach((game, socketId) => {
const user = getUserBySocket(socketId);
if (user && user.blockRec && currentHeight > user.blockRec + 1) {
// Game has timed out - player didn't escape in time
game.gameState = 'lost';
io.to(socketId).emit('game_over', {
status: 'lost',
reason: 'timeout',
message: 'You didn\'t escape before the next block was found!'
});
activeGames.delete(socketId);
}
});
}
// Socket.io handlers
io.on('connection', function(socket) {
console.log('A user connected');
console.log(socket.client.id);
console.log(socket.handshake.address);
db.insertVisitor(socket.client.id, socket.handshake.address, 0);
users.push(new user.User(socket.client.id, socket.handshake.address));
io.to(`${socket.client.id}`).emit('welcome', socket.client.id);
socket.on('chat message', function(msg) {
console.log(msg);
if (msg.toLowerCase() == 'hello') {
io.to(`${socket.client.id}`).emit('message',
'Welcome, to enter the dungeon type Enter, and you will be given a Wownero address, ' +
'which you must send between 10-100 WOW to enter. The more you send, the more you can win.');
}
else if (msg.toLowerCase() == 'enter') {
const currentUser = getUserBySocket(socket.client.id);
if (currentUser) {
// FOR TESTING: Skip payment and directly queue the player
currentUser.verifyPayment(10); // Minimal test fee
WAITING_PLAYERS.push(socket.client.id);
io.to(`${socket.client.id}`).emit('message',
'For testing: You will enter the dungeon when the next block is found.');
// To test without waiting for a block, immediately start a game
startGameForPlayer(socket.client.id, lastBlockHeight || 1);
}
}
else {
io.emit('message', msg);
}
});
// Handle player movement
socket.on('move', function(direction) {
const game = activeGames.get(socket.client.id);
if (game) {
let dx = 0, dy = 0;
// Convert direction to dx,dy
switch(direction) {
case 'up': dy = -1; break;
case 'down': dy = 1; break;
case 'left': dx = -1; break;
case 'right': dx = 1; break;
}
const result = game.movePlayer(dx, dy);
// Send updated game state
socket.emit('game_update', {
player: game.player,
monster: game.monster,
status: result.status
});
// Handle win/lose conditions
if (result.status === 'won') {
const user = getUserBySocket(socket.client.id);
const reward = user.calculateReward();
socket.emit('game_over', {
status: 'won',
hasTreasure: game.player.hasTreasure,
reward: reward
});
// TODO: Process payout
activeGames.delete(socket.client.id);
}
else if (result.status === 'lost') {
socket.emit('game_over', {
status: 'lost',
reason: result.reason
});
activeGames.delete(socket.client.id);
}
}
});
// Handle disconnection
socket.on('disconnect', function () {
console.log('A user disconnected');
// Clean up any active games
if (activeGames.has(socket.client.id)) {
activeGames.delete(socket.client.id);
}
users = spliceOut(socket.client.id, "socketid", users);
});
});
http.listen(3000, function() {
console.log('listening on *:3000');
});
// Remove objects from an array if one attribute matches
function spliceOut(target, field, array) {
for (var i = array.length - 1; i >= 0; --i) {
if (array[i][field] == target) {
array.splice(i,1);
}
}
return array;
}
// Check if objects are in an array if one attribute matches
function checkArray(target, field, array) {
for (var i = array.length - 1; i >= 0; --i) {
if (array[i][field] == target) {
return true;
}
}
return false;
}
// Add this function to generate a dungeon
function generateDungeon(width, height) {
// Create a new instance of ROT.Map.Digger
const digger = new ROT.Map.Digger(width, height, {
roomWidth: [3, 9],
roomHeight: [3, 5],
corridorLength: [2, 5],
dugPercentage: 0.2
});
// Create a map representation
const map = Array(height).fill().map(() => Array(width).fill(1)); // 1 = wall
// Callback to dig out rooms and corridors
digger.create((x, y, value) => {
map[y][x] = value; // 0 = floor, 1 = wall
});
// Get rooms and place special features
const rooms = digger.getRooms();
let entrance = null;
let exit = null;
let treasure = null;
if (rooms.length > 0) {
// Place entrance in the first room
entrance = rooms[0].getCenter();
// Place exit in the last room
exit = rooms[rooms.length-1].getCenter();
// Place treasure in a middle room
const treasureRoom = rooms[Math.floor(rooms.length/2)];
treasure = treasureRoom.getCenter();
}
return {
map: map,
entrance: entrance,
exit: exit,
treasure: treasure,
rooms: rooms
};
}
// Add this helper function to start a game for a specific player immediately:
function startGameForPlayer(socketId, blockHeight) {
const user = getUserBySocket(socketId);
if (user) {
user.blockRec = blockHeight;
const game = user.startGame(25, 19); // Create a new game with dimensions matching our display
activeGames.set(socketId, game);
io.to(socketId).emit('game_start', {
map: game.dungeon.map,
player: game.player,
monster: game.monster,
entrance: game.dungeon.entrance,
exit: game.dungeon.exit,
treasure: game.dungeon.treasure,
blockHeight: blockHeight
});
}
}