This repository has been archived on 2026-05-04. You can view files and clone it, but cannot push or open issues or pull requests.
Galaxy-Strike-Online/Client/js/systems/ItemSystem.js

384 lines
12 KiB
JavaScript

/**
* Galaxy Strike Online - Client Item System
* Dynamically loads and manages items from the GameServer
*/
class ItemSystem {
constructor(gameEngine) {
this.game = gameEngine;
// Item storage
this.itemCatalog = new Map(); // itemId -> item data
this.shopItems = []; // Array of shop items
this.lastUpdated = null;
// Loading state
this.isLoading = false;
this.loadPromise = null;
// Event listeners
this.eventListeners = new Map();
}
/**
* Initialize the item system and load data from server
*/
async initialize() {
console.log('[ITEM SYSTEM] Initializing client item system');
if (this.loadPromise) {
return this.loadPromise;
}
this.loadPromise = this.loadFromServer();
return this.loadPromise;
}
/**
* Load all items from the GameServer
*/
async loadFromServer() {
if (this.isLoading) {
console.log('[ITEM SYSTEM] Already loading items from server');
return this.loadPromise;
}
this.isLoading = true;
try {
console.log('[ITEM SYSTEM] Loading items from GameServer - Multiplayer Mode');
console.log('[ITEM SYSTEM] Socket connection status:', !!window.game?.socket);
if (!window.game || !window.game.socket) {
throw new Error('Not connected to server - multiplayer mode requires server connection');
}
// Load shop items from server
const shopItems = await this.fetchShopItems();
console.log('[ITEM SYSTEM] Received', shopItems.length, 'items from server');
// Process and store items
this.processServerItems(shopItems);
this.lastUpdated = Date.now();
console.log(`[ITEM SYSTEM] Successfully loaded ${this.itemCatalog.size} items from server`);
console.log('[ITEM SYSTEM] Item categories loaded:', Object.keys(this.itemCatalog).length);
// Emit loaded event
this.emit('itemsLoaded', {
itemCount: this.itemCatalog.size,
shopItemCount: this.shopItems.length,
timestamp: this.lastUpdated
});
return true;
} catch (error) {
console.error('[ITEM SYSTEM] Failed to load items from server:', error);
console.error('[ITEM SYSTEM] Error details:', {
message: error.message,
stack: error.stack,
socketConnected: !!window.game?.socket,
socketId: window.game?.socket?.id
});
// No fallback - emit error event
this.emit('itemsLoadError', error);
return false;
} finally {
this.isLoading = false;
}
}
/**
* Fetch shop items from the GameServer
*/
async fetchShopItems() {
console.log('[ITEM SYSTEM] Starting fetchShopItems');
if (!window.game || !window.game.socket) {
console.error('[ITEM SYSTEM] No socket connection available');
throw new Error('Not connected to server');
}
console.log('[ITEM SYSTEM] Socket ID:', window.game.socket.id);
console.log('[ITEM SYSTEM] Socket connected:', window.game.socket.connected);
return new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
console.error('[ITEM SYSTEM] Server request timeout after 10 seconds');
window.game.socket.off('shopItemsReceived', handleResponse);
reject(new Error('Server request timeout'));
}, 10000);
// Request shop items from server
console.log('[ITEM SYSTEM] Emitting getShopItems request');
window.game.socket.emit('getShopItems', {});
// Listen for response
const handleResponse = (data) => {
console.log('[ITEM SYSTEM] Received shopItemsReceived response:', data);
clearTimeout(timeout);
window.game.socket.off('shopItemsReceived', handleResponse);
if (data.success) {
console.log('[ITEM SYSTEM] Successfully received', data.items?.length || 0, 'items');
console.log('[ITEM SYSTEM] Response timestamp:', data.timestamp);
resolve(data.items || []);
} else {
console.error('[ITEM SYSTEM] Server returned error:', data.error);
reject(new Error(data.error || 'Failed to load shop items'));
}
};
console.log('[ITEM SYSTEM] Setting up shopItemsReceived listener');
window.game.socket.on('shopItemsReceived', handleResponse);
});
}
/**
* Fetch specific item details from server
*/
async fetchItemDetails(itemId) {
if (!window.game || !window.game.socket) {
throw new Error('Not connected to server');
}
return new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
reject(new Error('Server request timeout'));
}, 5000);
// Request item details from server
window.game.socket.emit('getItemDetails', { itemId });
// Listen for response
const handleResponse = (data) => {
clearTimeout(timeout);
window.game.socket.off('itemDetailsReceived', handleResponse);
if (data.success) {
// Cache the item
this.itemCatalog.set(itemId, data.item);
resolve(data.item);
} else {
reject(new Error(data.error || 'Item not found'));
}
};
window.game.socket.on('itemDetailsReceived', handleResponse);
});
}
/**
* Process items received from server
*/
processServerItems(items) {
console.log('[ITEM SYSTEM] Processing', items.length, 'items from server');
console.log('[ITEM SYSTEM] Sample items:', items.slice(0, 3));
this.itemCatalog.clear();
this.shopItems = [];
for (const item of items) {
// Store in catalog
this.itemCatalog.set(item.id, item);
// Add to shop items if available for shop
if (item.categories && item.categories.includes('shop')) {
this.shopItems.push(item);
}
console.log('[ITEM SYSTEM] Added item:', {
id: item.id,
name: item.name,
type: item.type,
rarity: item.rarity,
price: item.price,
categories: item.categories
});
}
console.log('[ITEM SYSTEM] Processing complete - Catalog:', this.itemCatalog.size, 'Shop items:', this.shopItems.length);
console.log('[ITEM SYSTEM] Shop items by type:', this.shopItems.reduce((acc, item) => {
acc[item.type] = (acc[item.type] || 0) + 1;
return acc;
}, {}));
}
/**
* Get item by ID
*/
getItem(itemId) {
// Return from cache if available
if (this.itemCatalog.has(itemId)) {
return this.itemCatalog.get(itemId);
}
// Try to fetch from server if not cached
if (window.game && window.game.socket) {
this.fetchItemDetails(itemId).catch(error => {
console.warn(`[ITEM SYSTEM] Failed to fetch item ${itemId}:`, error);
});
}
return null;
}
/**
* Get all shop items
*/
getShopItems() {
return [...this.shopItems];
}
/**
* Get items by category
*/
getItemsByCategory(category) {
return Array.from(this.itemCatalog.values()).filter(item =>
item.type === category || (item.categories && item.categories.includes(category))
);
}
/**
* Get items by type
*/
getItemsByType(type) {
return Array.from(this.itemCatalog.values()).filter(item => item.type === type);
}
/**
* Get items by rarity
*/
getItemsByRarity(rarity) {
return Array.from(this.itemCatalog.values()).filter(item => item.rarity === rarity);
}
/**
* Check if player can use item based on requirements
*/
canPlayerUseItem(item, playerLevel = null) {
if (!item.requirements) return true;
// Get player level if not provided
if (playerLevel === null && window.game && window.game.systems && window.game.systems.player) {
playerLevel = window.game.systems.player.level;
}
// Check level requirement
if (item.requirements.level && playerLevel < item.requirements.level) {
return false;
}
// Add other requirement checks here
return true;
}
/**
* Get filtered shop items for current player
*/
getAvailableShopItems() {
return this.shopItems.filter(item => this.canPlayerUseItem(item));
}
/**
* Format item price for display
*/
formatPrice(item) {
if (!item.price) return 'Free';
const currency = item.currency || 'credits';
const price = this.game.formatNumber(item.price);
return `${price} ${currency}`;
}
/**
* Get item rarity color
*/
getRarityColor(rarity) {
const colors = {
common: '#888888',
uncommon: '#00ff00',
rare: '#0088ff',
legendary: '#ff8800',
epic: '#ff00ff'
};
return colors[rarity] || '#ffffff';
}
/**
* Refresh items from server
*/
async refresh() {
console.log('[ITEM SYSTEM] Refreshing items from server');
return this.loadFromServer();
}
/**
* Event system
*/
on(event, callback) {
if (!this.eventListeners.has(event)) {
this.eventListeners.set(event, []);
}
this.eventListeners.get(event).push(callback);
}
off(event, callback) {
if (this.eventListeners.has(event)) {
const listeners = this.eventListeners.get(event);
const index = listeners.indexOf(callback);
if (index > -1) {
listeners.splice(index, 1);
}
}
}
emit(event, data) {
if (this.eventListeners.has(event)) {
for (const callback of this.eventListeners.get(event)) {
try {
callback(data);
} catch (error) {
console.error(`[ITEM SYSTEM] Error in event listener for ${event}:`, error);
}
}
}
}
/**
* Get system statistics
*/
getStats() {
const stats = {
totalItems: this.itemCatalog.size,
shopItems: this.shopItems.length,
lastUpdated: this.lastUpdated,
isLoading: this.isLoading,
socketConnected: !!(window.game?.socket),
socketId: window.game?.socket?.id
};
// Add category breakdown
stats.categories = {};
for (const item of this.itemCatalog.values()) {
stats.categories[item.type] = (stats.categories[item.type] || 0) + 1;
}
return stats;
}
}
// Export for use in other modules
if (typeof module !== 'undefined' && module.exports) {
module.exports = ItemSystem;
} else {
window.ItemSystem = ItemSystem;
}