mirror of
https://github.com/Such-Software/wownerogue.git
synced 2026-11-12 02:03:53 +01:00
286 lines
8.0 KiB
JavaScript
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
|
|
});
|
|
}
|
|
}
|