536 lines
21 KiB
JavaScript
536 lines
21 KiB
JavaScript
/**
|
|
* Simple Local Server for Singleplayer Mode
|
|
* A mock server that simulates server responses without requiring Node.js dependencies
|
|
* This runs entirely in the browser/renderer context
|
|
*/
|
|
|
|
class SimpleLocalServer {
|
|
constructor() {
|
|
this.isRunning = false;
|
|
this.port = 3004;
|
|
this.connectedClients = new Map();
|
|
this.existingSaveData = null;
|
|
|
|
// Check for existing save data on initialization
|
|
this.loadExistingSaveData();
|
|
|
|
this.mockData = {
|
|
servers: [{
|
|
id: 'local-server',
|
|
name: 'Local Singleplayer',
|
|
description: 'Your personal local server for singleplayer gaming',
|
|
type: 'private',
|
|
region: 'local',
|
|
maxPlayers: 1,
|
|
currentPlayers: 0,
|
|
owner: 'Local Player',
|
|
address: 'localhost',
|
|
port: this.port,
|
|
status: 'online',
|
|
createdAt: new Date().toISOString(),
|
|
ping: 0
|
|
}],
|
|
user: {
|
|
id: 'local-user',
|
|
email: 'local@player.com',
|
|
username: 'Local Player',
|
|
token: 'local-token-' + Date.now(),
|
|
createdAt: new Date().toISOString()
|
|
}
|
|
};
|
|
|
|
console.log('[SIMPLE LOCAL SERVER] SimpleLocalServer initialized');
|
|
console.log('[SIMPLE LOCAL SERVER] Existing save data found:', !!this.existingSaveData);
|
|
}
|
|
|
|
// Mock Socket.IO server for local mode
|
|
createMockSocket() {
|
|
console.log('[SIMPLE LOCAL SERVER] Creating mock Socket.IO connection');
|
|
|
|
const mockSocket = {
|
|
connected: false,
|
|
eventHandlers: {},
|
|
|
|
on: function(event, handler) {
|
|
console.log(`[MOCKET SOCKET] Registering event handler for: ${event}`);
|
|
if (!this.eventHandlers[event]) {
|
|
this.eventHandlers[event] = [];
|
|
}
|
|
this.eventHandlers[event].push(handler);
|
|
},
|
|
|
|
emit: function(event, data) {
|
|
console.log(`[MOCKET SOCKET] Emitting event: ${event}`, data);
|
|
},
|
|
|
|
connect: function() {
|
|
console.log('[MOCKET SOCKET] Connecting...');
|
|
this.connected = true;
|
|
|
|
// Simulate successful connection
|
|
setTimeout(() => {
|
|
if (this.eventHandlers['connect']) {
|
|
this.eventHandlers['connect'].forEach(handler => handler());
|
|
}
|
|
}, 100);
|
|
},
|
|
|
|
disconnect: function() {
|
|
console.log('[MOCKET SOCKET] Disconnecting...');
|
|
this.connected = false;
|
|
if (this.eventHandlers['disconnect']) {
|
|
this.eventHandlers['disconnect'].forEach(handler => handler());
|
|
}
|
|
}
|
|
};
|
|
|
|
// Auto-connect
|
|
mockSocket.connect();
|
|
|
|
return mockSocket;
|
|
}
|
|
|
|
loadExistingSaveData() {
|
|
try {
|
|
const saveData = localStorage.getItem(`gso_save_slot_1`);
|
|
if (saveData) {
|
|
this.existingSaveData = JSON.parse(saveData);
|
|
console.log('[SIMPLE LOCAL SERVER] Loaded existing save data:', {
|
|
hasPlayerData: !!this.existingSaveData.player,
|
|
playerLevel: this.existingSaveData.player?.stats?.level,
|
|
lastSave: this.existingSaveData.lastSave,
|
|
gameTime: this.existingSaveData.gameTime
|
|
});
|
|
} else {
|
|
console.log('[SIMPLE LOCAL SERVER] No existing save data found');
|
|
}
|
|
} catch (error) {
|
|
console.warn('[SIMPLE LOCAL SERVER] Error loading existing save data:', error);
|
|
this.existingSaveData = null;
|
|
}
|
|
}
|
|
|
|
applyExistingSaveDataToGame() {
|
|
if (!this.existingSaveData || !window.game) {
|
|
console.log('[SIMPLE LOCAL SERVER] No existing save data or game not available');
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
console.log('[SIMPLE LOCAL SERVER] Applying existing save data to game...');
|
|
|
|
// Apply save data to game systems
|
|
if (this.existingSaveData.player && window.game.systems.player) {
|
|
window.game.systems.player.load(this.existingSaveData.player);
|
|
console.log('[SIMPLE LOCAL SERVER] Player data applied');
|
|
}
|
|
|
|
if (this.existingSaveData.inventory && window.game.systems.inventory) {
|
|
window.game.systems.inventory.load(this.existingSaveData.inventory);
|
|
console.log('[SIMPLE LOCAL SERVER] Inventory data applied');
|
|
}
|
|
|
|
if (this.existingSaveData.economy && window.game.systems.economy) {
|
|
window.game.systems.economy.load(this.existingSaveData.economy);
|
|
console.log('[SIMPLE LOCAL SERVER] Economy data applied');
|
|
}
|
|
|
|
if (this.existingSaveData.idleSystem && window.game.systems.idleSystem) {
|
|
window.game.systems.idleSystem.load(this.existingSaveData.idleSystem);
|
|
console.log('[SIMPLE LOCAL SERVER] Idle system data applied');
|
|
}
|
|
|
|
if (this.existingSaveData.dungeonSystem && window.game.systems.dungeonSystem) {
|
|
window.game.systems.dungeonSystem.load(this.existingSaveData.dungeonSystem);
|
|
console.log('[SIMPLE LOCAL SERVER] Dungeon system data applied');
|
|
}
|
|
|
|
if (this.existingSaveData.skillSystem && window.game.systems.skillSystem) {
|
|
window.game.systems.skillSystem.load(this.existingSaveData.skillSystem);
|
|
console.log('[SIMPLE LOCAL SERVER] Skill system data applied');
|
|
}
|
|
|
|
if (this.existingSaveData.baseSystem && window.game.systems.baseSystem) {
|
|
window.game.systems.baseSystem.load(this.existingSaveData.baseSystem);
|
|
console.log('[SIMPLE LOCAL SERVER] Base system data applied');
|
|
}
|
|
|
|
if (this.existingSaveData.questSystem && window.game.systems.questSystem) {
|
|
window.game.systems.questSystem.load(this.existingSaveData.questSystem);
|
|
console.log('[SIMPLE LOCAL SERVER] Quest system data applied');
|
|
}
|
|
|
|
if (this.existingSaveData.gameTime && window.game) {
|
|
window.game.gameTime = this.existingSaveData.gameTime;
|
|
console.log('[SIMPLE LOCAL SERVER] Game time applied:', this.existingSaveData.gameTime);
|
|
}
|
|
|
|
console.log('[SIMPLE LOCAL SERVER] All save data applied successfully');
|
|
return true;
|
|
|
|
} catch (error) {
|
|
console.error('[SIMPLE LOCAL SERVER] Error applying save data to game:', error);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
async start(port = 3004) {
|
|
if (this.isRunning) {
|
|
console.log('[SIMPLE LOCAL SERVER] Server is already running on port', this.port);
|
|
return { success: false, error: 'Server already running' };
|
|
}
|
|
|
|
try {
|
|
this.port = port;
|
|
this.isRunning = true;
|
|
|
|
// Update mock server data with actual port
|
|
this.mockData.servers[0].port = port;
|
|
|
|
console.log(`[SIMPLE LOCAL SERVER] Mock local server started on port ${port}`);
|
|
|
|
return {
|
|
success: true,
|
|
port: port,
|
|
url: `http://localhost:${port}`
|
|
};
|
|
|
|
} catch (error) {
|
|
console.error('[SIMPLE LOCAL SERVER] Failed to start server:', error);
|
|
return { success: false, error: error.message };
|
|
}
|
|
}
|
|
|
|
async stop() {
|
|
if (!this.isRunning) {
|
|
console.log('[SIMPLE LOCAL SERVER] Server is not running');
|
|
return { success: false, error: 'Server is not running' };
|
|
}
|
|
|
|
try {
|
|
this.isRunning = false;
|
|
this.connectedClients.clear();
|
|
|
|
console.log('[SIMPLE LOCAL SERVER] Mock local server stopped');
|
|
return { success: true };
|
|
|
|
} catch (error) {
|
|
console.error('[SIMPLE LOCAL SERVER] Failed to stop server:', error);
|
|
return { success: false, error: error.message };
|
|
}
|
|
}
|
|
|
|
getStatus() {
|
|
return {
|
|
isRunning: this.isRunning,
|
|
port: this.port,
|
|
connectedClients: this.connectedClients.size,
|
|
uptime: this.isRunning ? 0 : 0 // Mock uptime
|
|
};
|
|
}
|
|
|
|
getUrl() {
|
|
return this.isRunning ? `http://localhost:${this.port}` : null;
|
|
}
|
|
|
|
// Mock API methods that simulate server responses
|
|
async mockRequest(method, url, data = null) {
|
|
console.log(`[SIMPLE LOCAL SERVER] Mock ${method} ${url}`, data);
|
|
|
|
// Simulate network delay
|
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
|
|
try {
|
|
if (url === '/health') {
|
|
return {
|
|
status: 200,
|
|
ok: true,
|
|
headers: {
|
|
get: (name) => name === 'content-type' ? 'application/json' : null
|
|
},
|
|
json: () => Promise.resolve({
|
|
status: 'OK',
|
|
timestamp: new Date().toISOString(),
|
|
uptime: 0,
|
|
mode: 'local'
|
|
}),
|
|
text: () => Promise.resolve(JSON.stringify({
|
|
status: 'OK',
|
|
timestamp: new Date().toISOString(),
|
|
uptime: 0,
|
|
mode: 'local'
|
|
}))
|
|
};
|
|
}
|
|
|
|
if (url === '/api/ssc/version') {
|
|
return {
|
|
status: 200,
|
|
ok: true,
|
|
headers: {
|
|
get: (name) => name === 'content-type' ? 'application/json' : null
|
|
},
|
|
json: () => Promise.resolve({
|
|
version: '1.0.0',
|
|
service: 'galaxystrikeonline-local-server',
|
|
timestamp: new Date().toISOString(),
|
|
mode: 'local'
|
|
}),
|
|
text: () => Promise.resolve(JSON.stringify({
|
|
version: '1.0.0',
|
|
service: 'galaxystrikeonline-local-server',
|
|
timestamp: new Date().toISOString(),
|
|
mode: 'local'
|
|
}))
|
|
};
|
|
}
|
|
|
|
if (url === '/api/auth/login' && method === 'POST') {
|
|
return {
|
|
status: 200,
|
|
ok: true,
|
|
headers: {
|
|
get: (name) => name === 'content-type' ? 'application/json' : null
|
|
},
|
|
json: () => Promise.resolve({
|
|
success: true,
|
|
user: this.mockData.user,
|
|
token: this.mockData.user.token,
|
|
message: 'Logged in to local mode'
|
|
}),
|
|
text: () => Promise.resolve(JSON.stringify({
|
|
success: true,
|
|
user: this.mockData.user,
|
|
token: this.mockData.user.token,
|
|
message: 'Logged in to local mode'
|
|
}))
|
|
};
|
|
}
|
|
|
|
if (url === '/api/auth/register' && method === 'POST') {
|
|
return {
|
|
status: 201,
|
|
ok: true,
|
|
headers: {
|
|
get: (name) => name === 'content-type' ? 'application/json' : null
|
|
},
|
|
json: () => Promise.resolve({
|
|
success: true,
|
|
user: this.mockData.user,
|
|
token: this.mockData.user.token,
|
|
message: 'Registered in local mode'
|
|
}),
|
|
text: () => Promise.resolve(JSON.stringify({
|
|
success: true,
|
|
user: this.mockData.user,
|
|
token: this.mockData.user.token,
|
|
message: 'Registered in local mode'
|
|
}))
|
|
};
|
|
}
|
|
|
|
if (url === '/api/servers') {
|
|
return {
|
|
status: 200,
|
|
ok: true,
|
|
headers: {
|
|
get: (name) => name === 'content-type' ? 'application/json' : null
|
|
},
|
|
json: () => Promise.resolve({
|
|
success: true,
|
|
servers: this.mockData.servers
|
|
}),
|
|
text: () => Promise.resolve(JSON.stringify({
|
|
success: true,
|
|
servers: this.mockData.servers
|
|
}))
|
|
};
|
|
}
|
|
|
|
if (url.startsWith('/servers/') && url.endsWith('/join') && method === 'POST') {
|
|
// Mock server join response
|
|
const serverId = url.split('/')[2];
|
|
return {
|
|
status: 200,
|
|
ok: true,
|
|
headers: {
|
|
get: (name) => name === 'content-type' ? 'application/json' : null
|
|
},
|
|
json: () => Promise.resolve({
|
|
success: true,
|
|
server: {
|
|
id: serverId,
|
|
name: 'Local Singleplayer',
|
|
address: 'localhost',
|
|
port: this.port,
|
|
gamePort: this.port + 1,
|
|
maxPlayers: 1,
|
|
currentPlayers: 1,
|
|
status: 'online'
|
|
},
|
|
message: 'Joined server successfully'
|
|
}),
|
|
text: () => Promise.resolve(JSON.stringify({
|
|
success: true,
|
|
server: {
|
|
id: serverId,
|
|
name: 'Local Singleplayer',
|
|
address: 'localhost',
|
|
port: this.port,
|
|
gamePort: this.port + 1,
|
|
maxPlayers: 1,
|
|
currentPlayers: 1,
|
|
status: 'online'
|
|
},
|
|
message: 'Joined server successfully'
|
|
}))
|
|
};
|
|
}
|
|
|
|
if (url.startsWith('/api/game/player/') && method === 'GET') {
|
|
// Return player data from existing save data or localStorage
|
|
let saveData = this.existingSaveData;
|
|
|
|
// If no existing save data, try localStorage
|
|
if (!saveData) {
|
|
try {
|
|
const localStorageData = localStorage.getItem(`gso_save_slot_1`);
|
|
if (localStorageData) {
|
|
saveData = JSON.parse(localStorageData);
|
|
}
|
|
} catch (error) {
|
|
console.warn('[SIMPLE LOCAL SERVER] Could not access localStorage:', error);
|
|
}
|
|
}
|
|
|
|
if (saveData) {
|
|
return {
|
|
status: 200,
|
|
ok: true,
|
|
headers: {
|
|
get: (name) => name === 'content-type' ? 'application/json' : null
|
|
},
|
|
json: () => Promise.resolve({
|
|
success: true,
|
|
player: saveData.player
|
|
}),
|
|
text: () => Promise.resolve(JSON.stringify({
|
|
success: true,
|
|
player: saveData.player
|
|
}))
|
|
};
|
|
} else {
|
|
return {
|
|
status: 404,
|
|
ok: false,
|
|
headers: {
|
|
get: (name) => name === 'content-type' ? 'application/json' : null
|
|
},
|
|
json: () => Promise.resolve({
|
|
success: false,
|
|
error: 'No save data found'
|
|
}),
|
|
text: () => Promise.resolve(JSON.stringify({
|
|
success: false,
|
|
error: 'No save data found'
|
|
}))
|
|
};
|
|
}
|
|
}
|
|
|
|
if (url.startsWith('/api/game/player/') && method === 'POST') {
|
|
// Save player data to localStorage
|
|
try {
|
|
let existingSaveData = '{}';
|
|
|
|
if (typeof localStorage !== 'undefined') {
|
|
existingSaveData = localStorage.getItem(`gso_save_slot_1`) || '{}';
|
|
}
|
|
|
|
const parsedExisting = JSON.parse(existingSaveData);
|
|
parsedExisting.player = data;
|
|
parsedExisting.lastSave = Date.now();
|
|
|
|
if (typeof localStorage !== 'undefined') {
|
|
localStorage.setItem(`gso_save_slot_1`, JSON.stringify(parsedExisting));
|
|
}
|
|
|
|
return {
|
|
status: 200,
|
|
ok: true,
|
|
headers: {
|
|
get: (name) => name === 'content-type' ? 'application/json' : null
|
|
},
|
|
json: () => Promise.resolve({
|
|
success: true,
|
|
message: 'Player data saved locally'
|
|
}),
|
|
text: () => Promise.resolve(JSON.stringify({
|
|
success: true,
|
|
message: 'Player data saved locally'
|
|
}))
|
|
};
|
|
} catch (error) {
|
|
return {
|
|
status: 500,
|
|
ok: false,
|
|
headers: {
|
|
get: (name) => name === 'content-type' ? 'application/json' : null
|
|
},
|
|
json: () => Promise.resolve({
|
|
success: false,
|
|
error: 'Failed to save player data'
|
|
}),
|
|
text: () => Promise.resolve(JSON.stringify({
|
|
success: false,
|
|
error: 'Failed to save player data'
|
|
}))
|
|
};
|
|
}
|
|
}
|
|
|
|
// Default response for unknown endpoints
|
|
return {
|
|
status: 404,
|
|
ok: false,
|
|
headers: {
|
|
get: (name) => name === 'content-type' ? 'application/json' : null
|
|
},
|
|
json: () => Promise.resolve({
|
|
success: false,
|
|
error: 'Endpoint not found'
|
|
}),
|
|
text: () => Promise.resolve(JSON.stringify({
|
|
success: false,
|
|
error: 'Endpoint not found'
|
|
}))
|
|
};
|
|
|
|
} catch (error) {
|
|
console.error('[SIMPLE LOCAL SERVER] Mock request error:', error);
|
|
return {
|
|
status: 500,
|
|
ok: false,
|
|
headers: {
|
|
get: (name) => name === 'content-type' ? 'application/json' : null
|
|
},
|
|
json: () => Promise.resolve({
|
|
success: false,
|
|
error: 'Internal server error'
|
|
}),
|
|
text: () => Promise.resolve(JSON.stringify({
|
|
success: false,
|
|
error: 'Internal server error'
|
|
}))
|
|
};
|
|
}
|
|
}
|
|
}
|
|
|
|
// Export for use in browser environment
|
|
if (typeof window !== 'undefined') {
|
|
window.SimpleLocalServer = SimpleLocalServer;
|
|
}
|
|
|
|
console.log('[SIMPLE LOCAL SERVER] SimpleLocalServer loaded and exported to window');
|