diff --git a/html/js/network/socketHandlers.js b/html/js/network/socketHandlers.js
index 267270a..8d71e52 100644
--- a/html/js/network/socketHandlers.js
+++ b/html/js/network/socketHandlers.js
@@ -94,6 +94,7 @@ const SocketHandlers = {
socket.on('payment_detected', this.onPaymentDetected);
socket.on('show_payment_options', this.onShowPaymentOptions);
socket.on('credits_update', this.onCreditsUpdate);
+ socket.on('user_count', this.onUserCount);
// Block height handler
socket.on('blockheight', this.onBlockHeight);
@@ -704,6 +705,29 @@ const SocketHandlers = {
}
},
+ onUserCount: function(data) {
+ if (!data || typeof data.count !== 'number') return;
+ SocketHandlers._updateUserCountDisplay(data.count);
+ },
+
+ _updateUserCountDisplay: function(count) {
+ let el = document.getElementById('userCountDisplay');
+ if (!el) {
+ // Create display element next to connection status
+ const statusDiv = document.querySelector('.status') || document.getElementById('connectionStatus')?.parentElement;
+ if (statusDiv) {
+ el = document.createElement('div');
+ el.id = 'userCountDisplay';
+ el.style.cssText = 'font-size:12px;color:#0af;margin-top:2px;';
+ statusDiv.appendChild(el);
+ }
+ }
+ if (el) {
+ const plural = count === 1 ? '' : 's';
+ el.innerHTML = `👥 ${count} player${plural} online`;
+ }
+ },
+
// ====== SPECTATOR HANDLERS ======
_spectatorMode: false,
diff --git a/src/game/gameModeManager.js b/src/game/gameModeManager.js
index 002ce87..71526b7 100644
--- a/src/game/gameModeManager.js
+++ b/src/game/gameModeManager.js
@@ -73,8 +73,8 @@ class GameModeManager {
this.singleGamePrice = parseAtomicEnvValue(process.env.SINGLE_GAME_PRICE, this.singleGamePrice);
this.creditsPackagePrice = parseAtomicEnvValue(process.env.CREDITS_PACKAGE_PRICE, this.creditsPackagePrice);
this.creditsPerGameCost = parseAtomicEnvValue(process.env.CREDITS_PER_GAME, 1) || 1;
- this.creditsPayoutEnabled = /^true$/i.test(process.env.CREDITS_PAYOUT_ENABLED || 'false');
- this.creditsPayoutBaseValue = this.singleGamePrice;
+ this.creditsPayoutEnabled = /^true$/i.test(process.env.CREDITS_PAYOUTS_ENABLED || process.env.CREDITS_PAYOUT_ENABLED || 'false');
+ this.creditsPayoutBaseValue = parseAtomicEnvValue(process.env.CREDITS_PAYOUT_BASE, this.singleGamePrice);
process.env.CREDITS_PER_GAME = String(this.creditsPerGameCost);
const directEscape = Number(process.env.DIRECT_PAYOUT_ESCAPE);
@@ -370,7 +370,7 @@ class GameModeManager {
console.log(`🧮 Payout multipliers - direct: ${JSON.stringify(this.directPayoutMultipliers)}, credits: ${JSON.stringify(this.creditPayoutMultipliers)}`);
console.log(`🔁 Mode availability - direct: ${this.directModeEnabled}, credits: ${this.creditsModeEnabled}, preferCreditsFirst: ${this.preferCreditsFirst}`);
if (this.creditsPayoutEnabled) {
- console.log('🎁 Credits payout mode ENABLED (will pay rewards in PAID_CREDITS).');
+ console.log(`🎁 Credits payout mode ENABLED - base value: ${this.creditsPayoutBaseValue} atomic (~${this.formatAtomic(this.creditsPayoutBaseValue)} ${this.cryptoType})`);
}
console.log(`⚙️ Payments enabled: ${this.paymentsEnabled}`);
}
@@ -1011,6 +1011,9 @@ class GameModeManager {
* Get game mode info for frontend
*/
getGameModeInfo() {
+ // Debug: Log credits payout base value being sent
+ console.log(`📤 getGameModeInfo: creditsPayoutBaseValue = ${this.creditsPayoutBaseValue} (${this.formatAtomic(this.creditsPayoutBaseValue)} ${this.cryptoType})`);
+
// Determine if we should show a testnet warning
// Only for XMR on stagenet/testnet - WOW only has mainnet
const showTestnetWarning = this.cryptoType === 'XMR' && this.isTestNetwork;
diff --git a/src/network/broadcastManager.js b/src/network/broadcastManager.js
index 047e5f4..7be5e43 100644
--- a/src/network/broadcastManager.js
+++ b/src/network/broadcastManager.js
@@ -8,10 +8,23 @@ class BroadcastManager {
constructor(io) {
this.io = io;
this._lastBroadcastBlock = null;
+ this._lastUserCount = -1;
}
// ====== GLOBAL BROADCASTS (All Clients) ======
+ /**
+ * Broadcast connected user count to all clients
+ */
+ broadcastUserCount() {
+ const count = this.io.engine ? this.io.engine.clientsCount : 0;
+ // Only broadcast if count changed to avoid spam
+ if (count !== this._lastUserCount) {
+ this._lastUserCount = count;
+ this.io.emit('user_count', { count });
+ }
+ }
+
/**
* Broadcast block height to all connected clients
* @param {number} blockHeight - Current block height
diff --git a/src/network/connectionHandler.js b/src/network/connectionHandler.js
index 1720574..1aa8c18 100644
--- a/src/network/connectionHandler.js
+++ b/src/network/connectionHandler.js
@@ -64,6 +64,9 @@ class ConnectionHandler {
// Send current state
this._sendConnectionStatus(socket);
+ // Broadcast updated user count to all clients
+ this.broadcastManager.broadcastUserCount();
+
return { sessionInfo, memUser };
} catch (error) {
@@ -112,6 +115,9 @@ class ConnectionHandler {
// Clean up user records
user.removeUser(socket.client.id);
+ // Broadcast updated user count to all clients
+ this.broadcastManager.broadcastUserCount();
+
// Call additional cleanup if provided
if (additionalCleanup && typeof additionalCleanup === 'function') {
additionalCleanup(socket);