Major milestone: Frontend implementation complete for Shattered Void MMO FRONTEND IMPLEMENTATION: - React 18 + TypeScript + Vite development environment - Tailwind CSS with custom dark theme for sci-fi aesthetic - Zustand state management with authentication persistence - Socket.io WebSocket client with auto-reconnection - Protected routing with authentication guards - Responsive design with mobile-first approach AUTHENTICATION SYSTEM: - Login/register forms with comprehensive validation - JWT token management with localStorage persistence - Password strength validation and user feedback - Protected routes and authentication guards CORE GAME INTERFACE: - Colony management dashboard with real-time updates - Resource display with live production tracking - WebSocket integration for real-time game events - Navigation with connection status indicator - Toast notifications for user feedback BACKEND ENHANCEMENTS: - Complete Research System with technology tree (23 technologies) - Fleet Management System with ship designs and movement - Enhanced Authentication with email verification and password reset - Complete game tick integration for all systems - Advanced WebSocket events for real-time updates ARCHITECTURE FEATURES: - Type-safe TypeScript throughout - Component-based architecture with reusable UI elements - API client with request/response interceptors - Error handling and loading states - Performance optimized builds with code splitting Phase 2 Status: Frontend foundation complete (Week 1-2 objectives met) Ready for: Colony management, fleet operations, research interface Next: Enhanced gameplay features and admin interface 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
307 lines
7.3 KiB
JavaScript
307 lines
7.3 KiB
JavaScript
/**
|
|
* Player Management Controller
|
|
* Handles player-specific operations and game-related endpoints
|
|
*/
|
|
|
|
const PlayerService = require('../../services/user/PlayerService');
|
|
const { asyncHandler } = require('../../middleware/error.middleware');
|
|
const logger = require('../../utils/logger');
|
|
|
|
const playerService = new PlayerService();
|
|
|
|
/**
|
|
* Get player dashboard data
|
|
* GET /api/player/dashboard
|
|
*/
|
|
const getDashboard = asyncHandler(async (req, res) => {
|
|
const correlationId = req.correlationId;
|
|
const playerId = req.user.playerId;
|
|
|
|
logger.info('Player dashboard request received', {
|
|
correlationId,
|
|
playerId,
|
|
});
|
|
|
|
// Get player profile with resources and stats
|
|
const profile = await playerService.getPlayerProfile(playerId, correlationId);
|
|
|
|
// TODO: Add additional dashboard data such as:
|
|
// - Recent activities
|
|
// - Colony summaries
|
|
// - Fleet statuses
|
|
// - Research progress
|
|
// - Messages/notifications
|
|
|
|
const dashboardData = {
|
|
player: profile,
|
|
summary: {
|
|
totalColonies: profile.stats.coloniesCount,
|
|
totalFleets: profile.stats.fleetsCount,
|
|
totalBattles: profile.stats.totalBattles,
|
|
winRate: profile.stats.totalBattles > 0
|
|
? Math.round((profile.stats.battlesWon / profile.stats.totalBattles) * 100)
|
|
: 0,
|
|
},
|
|
// Placeholder for future dashboard sections
|
|
recentActivity: [],
|
|
notifications: [],
|
|
gameStatus: {
|
|
online: true,
|
|
lastTick: new Date().toISOString(),
|
|
},
|
|
};
|
|
|
|
logger.info('Player dashboard data retrieved', {
|
|
correlationId,
|
|
playerId,
|
|
username: profile.username,
|
|
});
|
|
|
|
res.status(200).json({
|
|
success: true,
|
|
message: 'Dashboard data retrieved successfully',
|
|
data: dashboardData,
|
|
correlationId,
|
|
});
|
|
});
|
|
|
|
/**
|
|
* Get player resources
|
|
* GET /api/player/resources
|
|
*/
|
|
const getResources = asyncHandler(async (req, res) => {
|
|
const correlationId = req.correlationId;
|
|
const playerId = req.user.playerId;
|
|
|
|
logger.info('Player resources request received', {
|
|
correlationId,
|
|
playerId,
|
|
});
|
|
|
|
const profile = await playerService.getPlayerProfile(playerId, correlationId);
|
|
|
|
logger.info('Player resources retrieved', {
|
|
correlationId,
|
|
playerId,
|
|
scrap: profile.resources.scrap,
|
|
energy: profile.resources.energy,
|
|
});
|
|
|
|
res.status(200).json({
|
|
success: true,
|
|
message: 'Resources retrieved successfully',
|
|
data: {
|
|
resources: profile.resources,
|
|
lastUpdated: new Date().toISOString(),
|
|
},
|
|
correlationId,
|
|
});
|
|
});
|
|
|
|
/**
|
|
* Get player statistics
|
|
* GET /api/player/stats
|
|
*/
|
|
const getStats = asyncHandler(async (req, res) => {
|
|
const correlationId = req.correlationId;
|
|
const playerId = req.user.playerId;
|
|
|
|
logger.info('Player statistics request received', {
|
|
correlationId,
|
|
playerId,
|
|
});
|
|
|
|
const profile = await playerService.getPlayerProfile(playerId, correlationId);
|
|
|
|
const detailedStats = {
|
|
...profile.stats,
|
|
winRate: profile.stats.totalBattles > 0
|
|
? Math.round((profile.stats.battlesWon / profile.stats.totalBattles) * 100)
|
|
: 0,
|
|
lossRate: profile.stats.totalBattles > 0
|
|
? Math.round(((profile.stats.totalBattles - profile.stats.battlesWon) / profile.stats.totalBattles) * 100)
|
|
: 0,
|
|
accountAge: Math.floor((Date.now() - new Date(profile.createdAt).getTime()) / (1000 * 60 * 60 * 24)), // days
|
|
};
|
|
|
|
logger.info('Player statistics retrieved', {
|
|
correlationId,
|
|
playerId,
|
|
totalBattles: detailedStats.totalBattles,
|
|
winRate: detailedStats.winRate,
|
|
});
|
|
|
|
res.status(200).json({
|
|
success: true,
|
|
message: 'Statistics retrieved successfully',
|
|
data: {
|
|
stats: detailedStats,
|
|
lastUpdated: new Date().toISOString(),
|
|
},
|
|
correlationId,
|
|
});
|
|
});
|
|
|
|
/**
|
|
* Update player settings
|
|
* PUT /api/player/settings
|
|
*/
|
|
const updateSettings = asyncHandler(async (req, res) => {
|
|
const correlationId = req.correlationId;
|
|
const playerId = req.user.playerId;
|
|
const settings = req.body;
|
|
|
|
logger.info('Player settings update request received', {
|
|
correlationId,
|
|
playerId,
|
|
settingsKeys: Object.keys(settings),
|
|
});
|
|
|
|
// TODO: Implement player settings update
|
|
// This would involve:
|
|
// 1. Validate settings data
|
|
// 2. Update player_settings table
|
|
// 3. Return updated settings
|
|
|
|
logger.warn('Player settings update requested but not implemented', {
|
|
correlationId,
|
|
playerId,
|
|
});
|
|
|
|
res.status(501).json({
|
|
success: false,
|
|
message: 'Player settings update feature not yet implemented',
|
|
correlationId,
|
|
});
|
|
});
|
|
|
|
/**
|
|
* Get player activity log
|
|
* GET /api/player/activity
|
|
*/
|
|
const getActivity = asyncHandler(async (req, res) => {
|
|
const correlationId = req.correlationId;
|
|
const playerId = req.user.playerId;
|
|
const { page = 1, limit = 20 } = req.query;
|
|
|
|
logger.info('Player activity log request received', {
|
|
correlationId,
|
|
playerId,
|
|
page,
|
|
limit,
|
|
});
|
|
|
|
// TODO: Implement player activity log retrieval
|
|
// This would show recent actions like:
|
|
// - Colony creations/updates
|
|
// - Fleet movements
|
|
// - Research completions
|
|
// - Battle results
|
|
// - Resource transactions
|
|
|
|
const mockActivity = {
|
|
activities: [],
|
|
pagination: {
|
|
page: parseInt(page),
|
|
limit: parseInt(limit),
|
|
total: 0,
|
|
totalPages: 0,
|
|
hasNext: false,
|
|
hasPrev: false,
|
|
},
|
|
};
|
|
|
|
logger.info('Player activity log retrieved', {
|
|
correlationId,
|
|
playerId,
|
|
activitiesCount: mockActivity.activities.length,
|
|
});
|
|
|
|
res.status(200).json({
|
|
success: true,
|
|
message: 'Activity log retrieved successfully',
|
|
data: mockActivity,
|
|
correlationId,
|
|
});
|
|
});
|
|
|
|
/**
|
|
* Get player notifications
|
|
* GET /api/player/notifications
|
|
*/
|
|
const getNotifications = asyncHandler(async (req, res) => {
|
|
const correlationId = req.correlationId;
|
|
const playerId = req.user.playerId;
|
|
const { unreadOnly = false } = req.query;
|
|
|
|
logger.info('Player notifications request received', {
|
|
correlationId,
|
|
playerId,
|
|
unreadOnly,
|
|
});
|
|
|
|
// TODO: Implement player notifications retrieval
|
|
// This would show:
|
|
// - System messages
|
|
// - Battle results
|
|
// - Research completions
|
|
// - Fleet arrival notifications
|
|
// - Player messages
|
|
|
|
const mockNotifications = {
|
|
notifications: [],
|
|
unreadCount: 0,
|
|
totalCount: 0,
|
|
};
|
|
|
|
logger.info('Player notifications retrieved', {
|
|
correlationId,
|
|
playerId,
|
|
unreadCount: mockNotifications.unreadCount,
|
|
});
|
|
|
|
res.status(200).json({
|
|
success: true,
|
|
message: 'Notifications retrieved successfully',
|
|
data: mockNotifications,
|
|
correlationId,
|
|
});
|
|
});
|
|
|
|
/**
|
|
* Mark notifications as read
|
|
* PUT /api/player/notifications/read
|
|
*/
|
|
const markNotificationsRead = asyncHandler(async (req, res) => {
|
|
const correlationId = req.correlationId;
|
|
const playerId = req.user.playerId;
|
|
const { notificationIds } = req.body;
|
|
|
|
logger.info('Mark notifications read request received', {
|
|
correlationId,
|
|
playerId,
|
|
notificationCount: notificationIds?.length || 0,
|
|
});
|
|
|
|
// TODO: Implement notification marking as read
|
|
logger.warn('Mark notifications read requested but not implemented', {
|
|
correlationId,
|
|
playerId,
|
|
});
|
|
|
|
res.status(501).json({
|
|
success: false,
|
|
message: 'Mark notifications read feature not yet implemented',
|
|
correlationId,
|
|
});
|
|
});
|
|
|
|
module.exports = {
|
|
getDashboard,
|
|
getResources,
|
|
getStats,
|
|
updateSettings,
|
|
getActivity,
|
|
getNotifications,
|
|
markNotificationsRead,
|
|
};
|