more fixes, and merges

This commit is contained in:
Robert MacRae 2026-03-10 13:06:33 -03:00
parent 35eafd6026
commit 2933308999
282 changed files with 8470 additions and 2394 deletions

View File

@ -1,4 +1,5 @@
const express = require('express'); const express = require('express');
const errorReporter = require('./utils/ErrorReporter');
const http = require('http'); const http = require('http');
const cors = require('cors'); const cors = require('cors');
const helmet = require('helmet'); const helmet = require('helmet');
@ -57,6 +58,8 @@ app.use(cors({
})); }));
app.use(express.json({ limit: '10mb' })); app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true })); app.use(express.urlencoded({ extended: true }));
app.use(errorReporter.requestMiddleware());
app.get('/health', (req, res) => res.json({ status: 'ok', service: 'API', ...errorReporter.getMetrics() }));
// Static file serving // Static file serving
app.use(express.static('../Website/dist')); app.use(express.static('../Website/dist'));

View File

@ -1,272 +0,0 @@
const logger = require('../utils/logger');
const { getGameSystem } = require('../systems/GameSystem');
const Player = require('../models/Player');
class SocketHandlers {
constructor(io) {
this.io = io;
this.connectedUsers = new Map(); // userId -> socket.id
this.userSockets = new Map(); // socket.id -> userId
}
handleConnection(socket) {
logger.info(`Client connected: ${socket.id}`);
// Authentication
socket.on('authenticate', async (token) => {
try {
const jwt = require('jsonwebtoken');
const decoded = jwt.verify(token, process.env.JWT_SECRET || 'fallback_secret');
const player = await Player.findOne({ userId: decoded.userId });
if (!player) {
socket.emit('auth_error', { error: 'Player not found' });
return;
}
// Store user connection
this.connectedUsers.set(decoded.userId, socket.id);
this.userSockets.set(socket.id, decoded.userId);
socket.userId = decoded.userId;
socket.emit('authenticated', { userId: decoded.userId });
logger.info(`User authenticated: ${decoded.userId}`);
// Join user to their current server if any
if (player.currentServer) {
socket.join(player.currentServer);
this.broadcastToServer(player.currentServer, 'user_joined', {
userId: decoded.userId,
username: player.username
});
}
} catch (error) {
logger.error('Authentication error:', error);
socket.emit('auth_error', { error: 'Invalid token' });
}
});
// Server management
socket.on('join_server', async (data) => {
try {
if (!socket.userId) {
socket.emit('error', { error: 'Not authenticated' });
return;
}
const gameSystem = getGameSystem();
const server = await gameSystem.joinServer(data.serverId, socket.userId);
// Update player's current server
await Player.findOneAndUpdate(
{ userId: socket.userId },
{ currentServer: data.serverId }
);
// Join socket room
socket.join(data.serverId);
socket.emit('server_joined', { server });
this.broadcastToServer(data.serverId, 'user_joined', {
userId: socket.userId,
serverId: data.serverId
});
logger.info(`User ${socket.userId} joined server ${data.serverId}`);
} catch (error) {
logger.error('Error joining server:', error);
socket.emit('error', { error: error.message });
}
});
socket.on('leave_server', async (data) => {
try {
if (!socket.userId) {
socket.emit('error', { error: 'Not authenticated' });
return;
}
const gameSystem = getGameSystem();
const server = await gameSystem.leaveServer(data.serverId, socket.userId);
// Update player's current server
await Player.findOneAndUpdate(
{ userId: socket.userId },
{ currentServer: null }
);
// Leave socket room
socket.leave(data.serverId);
socket.emit('server_left', { server });
this.broadcastToServer(data.serverId, 'user_left', {
userId: socket.userId,
serverId: data.serverId
});
logger.info(`User ${socket.userId} left server ${data.serverId}`);
} catch (error) {
logger.error('Error leaving server:', error);
socket.emit('error', { error: error.message });
}
});
// Game actions
socket.on('game_action', async (data) => {
try {
if (!socket.userId) {
socket.emit('error', { error: 'Not authenticated' });
return;
}
const gameSystem = getGameSystem();
const result = await gameSystem.processGameAction(socket.userId, data);
socket.emit('action_result', { action: data.type, result });
// Broadcast relevant actions to server
if (data.broadcast && socket.userId) {
const player = await Player.findOne({ userId: socket.userId });
if (player && player.currentServer) {
this.broadcastToServer(player.currentServer, 'user_action', {
userId: socket.userId,
username: player.username,
action: data.type,
result
});
}
}
} catch (error) {
logger.error('Error processing game action:', error);
socket.emit('error', { error: error.message });
}
});
// Chat functionality
socket.on('send_message', async (data) => {
try {
if (!socket.userId) {
socket.emit('error', { error: 'Not authenticated' });
return;
}
const player = await Player.findOne({ userId: socket.userId });
if (!player || !player.currentServer) {
socket.emit('error', { error: 'Not in a server' });
return;
}
const message = {
userId: socket.userId,
username: player.username,
message: data.message,
timestamp: new Date(),
type: data.type || 'chat'
};
// Broadcast to server
this.broadcastToServer(player.currentServer, 'new_message', message);
logger.info(`Chat message from ${socket.userId} in server ${player.currentServer}`);
} catch (error) {
logger.error('Error sending message:', error);
socket.emit('error', { error: error.message });
}
});
// Real-time updates
socket.on('request_server_status', async () => {
try {
if (!socket.userId) {
socket.emit('error', { error: 'Not authenticated' });
return;
}
const player = await Player.findOne({ userId: socket.userId });
if (!player || !player.currentServer) {
socket.emit('server_status', { server: null });
return;
}
const gameSystem = getGameSystem();
const server = gameSystem.servers.get(player.currentServer);
if (server) {
const players = await Player.find({
userId: { $in: server.players }
}).select('userId username info.stats.level');
socket.emit('server_status', {
server: {
id: server.id,
name: server.name,
currentPlayers: server.players.length,
maxPlayers: server.maxPlayers,
players: players.map(p => ({
userId: p.userId,
username: p.username,
level: p.info.stats.level
}))
}
});
}
} catch (error) {
logger.error('Error getting server status:', error);
socket.emit('error', { error: error.message });
}
});
// Disconnection
socket.on('disconnect', async () => {
logger.info(`Client disconnected: ${socket.id}`);
const userId = this.userSockets.get(socket.id);
if (userId) {
// Remove from tracking
this.connectedUsers.delete(userId);
this.userSockets.delete(socket.id);
// Notify server if user was in one
const player = await Player.findOne({ userId });
if (player && player.currentServer) {
this.broadcastToServer(player.currentServer, 'user_disconnected', {
userId,
username: player.username
});
}
}
});
}
broadcastToServer(serverId, event, data) {
this.io.to(serverId).emit(event, data);
}
sendToUser(userId, event, data) {
const socketId = this.connectedUsers.get(userId);
if (socketId) {
this.io.to(socketId).emit(event, data);
}
}
broadcastToAll(event, data) {
this.io.emit(event, data);
}
getConnectedUsers() {
return Array.from(this.connectedUsers.keys());
}
getUserCount() {
return this.connectedUsers.size;
}
}
module.exports = SocketHandlers;

View File

@ -1,385 +0,0 @@
const logger = require('../utils/logger');
class EconomySystem {
constructor() {
this.shopItems = {
ships: [],
weapons: [],
armors: [],
materials: [],
consumables: []
};
this.dailyRewards = {
baseReward: 100,
consecutiveBonus: 50,
maxConsecutiveDays: 30
};
}
async initialize() {
logger.info('Initializing Economy System...');
// Initialize shop items
await this.initializeShopItems();
logger.info('Economy System initialized successfully');
}
async initializeShopItems() {
// Ships
this.shopItems.ships = [
// Starter Cruiser Variants
{
id: 'starter_cruiser_common',
name: 'Starter Cruiser',
type: 'ship',
rarity: 'common',
price: 5000,
currency: 'credits',
description: 'Reliable starter cruiser for new pilots',
texture: 'assets/textures/ships/starter_cruiser.png',
stats: { attack: 15, speed: 10, defense: 12, hull: 100 }
},
{
id: 'starter_cruiser_uncommon',
name: 'Starter Cruiser II',
type: 'ship',
rarity: 'uncommon',
price: 12000,
currency: 'credits',
description: 'Upgraded starter cruiser with enhanced systems',
texture: 'assets/textures/ships/starter_cruiser.png',
stats: { attack: 18, speed: 12, defense: 15, hull: 120 }
},
{
id: 'starter_cruiser_rare',
name: 'Starter Cruiser III',
type: 'ship',
rarity: 'rare',
price: 25000,
currency: 'credits',
description: 'Elite starter cruiser with advanced weaponry',
texture: 'assets/textures/ships/starter_cruiser.png',
stats: { attack: 22, speed: 14, defense: 18, hull: 140 }
},
{
id: 'starter_cruiser_epic',
name: 'Starter Cruiser IV',
type: 'ship',
rarity: 'epic',
price: 50000,
currency: 'credits',
description: 'Master starter cruiser with elite modifications',
texture: 'assets/textures/ships/starter_cruiser.png',
stats: { attack: 28, speed: 16, defense: 22, hull: 160 }
},
{
id: 'starter_cruiser_legendary',
name: 'Starter Cruiser V',
type: 'ship',
rarity: 'legendary',
price: 100000,
currency: 'credits',
description: 'Legendary starter cruiser with unparalleled performance',
texture: 'assets/textures/ships/starter_cruiser.png',
stats: { attack: 35, speed: 18, defense: 28, hull: 180 }
}
];
// Weapons
this.shopItems.weapons = [
// Starter Blaster Variants
{
id: 'starter_blaster_common',
name: 'Common Blaster',
type: 'weapon',
rarity: 'common',
price: 1000,
currency: 'credits',
description: 'Basic blaster for new pilots',
texture: 'assets/textures/weapons/starter_blaster.png',
stats: { damage: 10, fireRate: 2, range: 5, energy: 5 }
},
{
id: 'starter_blaster_uncommon',
name: 'Starter Blaster II',
type: 'weapon',
rarity: 'uncommon',
price: 2500,
currency: 'credits',
description: 'Improved blaster with better damage output',
texture: 'assets/textures/weapons/starter_blaster.png',
stats: { damage: 12, fireRate: 2.2, range: 5.5, energy: 6 }
},
{
id: 'starter_blaster_rare',
name: 'Starter Blaster III',
type: 'weapon',
rarity: 'rare',
price: 5000,
currency: 'credits',
description: 'Advanced blaster with enhanced capabilities',
texture: 'assets/textures/weapons/starter_blaster.png',
stats: { damage: 15, fireRate: 2.5, range: 6, energy: 7 }
},
{
id: 'starter_blaster_epic',
name: 'Starter Blaster IV',
type: 'weapon',
rarity: 'epic',
price: 10000,
currency: 'credits',
description: 'Elite blaster with superior performance',
texture: 'assets/textures/weapons/starter_blaster.png',
stats: { damage: 18, fireRate: 3, range: 6.5, energy: 8 }
},
{
id: 'starter_blaster_legendary',
name: 'Starter Blaster V',
type: 'weapon',
rarity: 'legendary',
price: 20000,
currency: 'credits',
description: 'Legendary starter blaster with ultimate power',
texture: 'assets/textures/weapons/starter_blaster.png',
stats: { damage: 22, fireRate: 4, range: 7, energy: 10 }
}
];
// Armors
this.shopItems.armors = [
// Basic Armor Variants
{
id: 'basic_armor_common',
name: 'Basic Armor',
type: 'armor',
rarity: 'common',
price: 1500,
currency: 'credits',
description: 'Light protection for beginners',
texture: 'assets/textures/armors/basic_armor.png',
stats: { defense: 5, durability: 20, weight: 2, energyShield: 0 }
},
{
id: 'basic_armor_uncommon',
name: 'Basic Armor II',
type: 'armor',
rarity: 'uncommon',
price: 4000,
currency: 'credits',
description: 'Improved basic armor with better durability',
texture: 'assets/textures/armors/basic_armor.png',
stats: { defense: 7, durability: 25, weight: 2.2, energyShield: 2 }
},
{
id: 'basic_armor_rare',
name: 'Basic Armor III',
type: 'armor',
rarity: 'rare',
price: 8000,
currency: 'credits',
description: 'Enhanced armor with energy shielding',
texture: 'assets/textures/armors/basic_armor.png',
stats: { defense: 10, durability: 30, weight: 2.5, energyShield: 5 }
},
{
id: 'basic_armor_epic',
name: 'Basic Armor IV',
type: 'armor',
rarity: 'epic',
price: 15000,
currency: 'credits',
description: 'Elite armor with advanced protection systems',
texture: 'assets/textures/armors/basic_armor.png',
stats: { defense: 15, durability: 35, weight: 3, energyShield: 10 }
},
{
id: 'basic_armor_legendary',
name: 'Basic Armor V',
type: 'armor',
rarity: 'legendary',
price: 30000,
currency: 'credits',
description: 'Legendary armor with ultimate protection',
texture: 'assets/textures/armors/basic_armor.png',
stats: { defense: 20, durability: 40, weight: 3.5, energyShield: 15 }
}
];
// Materials
this.shopItems.materials = [
{
id: 'iron_ore',
name: 'Iron Ore',
type: 'material',
rarity: 'common',
price: 50,
currency: 'credits',
description: 'Raw iron ore used for crafting basic weapons and armor',
stackable: true
},
{
id: 'copper_wire',
name: 'Copper Wire',
type: 'material',
rarity: 'common',
price: 75,
currency: 'credits',
description: 'Copper wiring used in electronic components',
stackable: true
},
{
id: 'energy_crystal',
name: 'Energy Crystal',
type: 'material',
rarity: 'uncommon',
price: 200,
currency: 'credits',
description: 'Crystallized energy used for powered equipment',
stackable: true
},
{
id: 'rare_metal',
name: 'Rare Metal',
type: 'material',
rarity: 'rare',
price: 500,
currency: 'credits',
description: 'Rare metallic alloy used for high-end crafting',
stackable: true
},
{
id: 'advanced_components',
name: 'Advanced Components',
type: 'material',
rarity: 'rare',
price: 1000,
currency: 'credits',
description: 'Sophisticated electronic components for advanced ship systems',
stackable: true
}
];
// Consumables
this.shopItems.consumables = [
{
id: 'health_kit',
name: 'Health Kit',
type: 'consumable',
rarity: 'common',
price: 100,
currency: 'credits',
description: 'A medical kit that restores health',
consumable: true,
effect: { health: 50 }
},
{
id: 'energy_pack',
name: 'Energy Pack',
type: 'consumable',
rarity: 'common',
price: 150,
currency: 'credits',
description: 'A pack that restores energy',
consumable: true,
effect: { energy: 25 }
},
{
id: 'repair_kit',
name: 'Repair Kit',
type: 'consumable',
rarity: 'uncommon',
price: 300,
currency: 'credits',
description: 'A kit that repairs ship damage',
consumable: true,
effect: { health: 100 }
}
];
logger.info(`Shop initialized with ${this.getTotalShopItems()} items`);
}
getTotalShopItems() {
return Object.values(this.shopItems).reduce((total, category) => total + category.length, 0);
}
getShopItems(category = null) {
if (category && this.shopItems[category]) {
return this.shopItems[category];
}
return this.shopItems;
}
getItem(itemId) {
for (const category of Object.values(this.shopItems)) {
const item = category.find(item => item.id === itemId);
if (item) return item;
}
return null;
}
purchaseItem(userId, itemId, quantity = 1) {
const item = this.getItem(itemId);
if (!item) {
throw new Error('Item not found in shop');
}
const totalCost = item.price * quantity;
return {
item,
quantity,
totalCost,
currency: item.currency
};
}
calculateDailyReward(consecutiveDays) {
const bonusMultiplier = Math.min(consecutiveDays - 1, this.dailyRewards.maxConsecutiveDays - 1);
const bonusAmount = bonusMultiplier * this.dailyRewards.consecutiveBonus;
const totalReward = this.dailyRewards.baseReward + bonusAmount;
return {
baseReward: this.dailyRewards.baseReward,
consecutiveBonus: bonusAmount,
totalReward,
consecutiveDays
};
}
getRandomShopItems(category, count = 6) {
const items = this.shopItems[category] || [];
const shuffled = [...items].sort(() => Math.random() - 0.5);
return shuffled.slice(0, Math.min(count, items.length));
}
refreshShopInventory() {
logger.info('Refreshing shop inventory...');
// This would typically involve database operations
// For now, we'll just log the refresh
return true;
}
getShopStats() {
const stats = {
totalItems: this.getTotalShopItems(),
itemsByCategory: {},
averagePriceByCategory: {}
};
for (const [category, items] of Object.entries(this.shopItems)) {
stats.itemsByCategory[category] = items.length;
if (items.length > 0) {
const totalPrice = items.reduce((sum, item) => sum + item.price, 0);
stats.averagePriceByCategory[category] = Math.round(totalPrice / items.length);
}
}
return stats;
}
}
module.exports = EconomySystem;

View File

@ -1,293 +0,0 @@
const logger = require('../utils/logger');
const Player = require('../models/Player');
const Ship = require('../models/Ship');
const Inventory = require('../models/Inventory');
const Economy = require('./EconomySystem');
class GameSystem {
constructor() {
this.players = new Map();
this.servers = new Map();
this.economy = new Economy();
}
async initializeGameSystems() {
logger.info('Initializing server-side game systems...');
// Initialize economy system
await this.economy.initialize();
logger.info('Game systems initialized successfully');
}
// Player management
async createPlayer(userId, playerData) {
try {
const player = new Player({
userId,
...playerData,
createdAt: new Date(),
lastLogin: new Date()
});
await player.save();
this.players.set(userId, player);
logger.info(`Created new player for user: ${userId}`);
return player;
} catch (error) {
logger.error('Error creating player:', error);
throw error;
}
}
async loadPlayer(userId) {
try {
let player = this.players.get(userId);
if (!player) {
player = await Player.findOne({ userId }).populate('ships inventory');
if (player) {
this.players.set(userId, player);
}
}
return player;
} catch (error) {
logger.error('Error loading player:', error);
throw error;
}
}
async savePlayer(userId) {
try {
const player = this.players.get(userId);
if (player) {
await player.save();
logger.info(`Saved player data for user: ${userId}`);
}
} catch (error) {
logger.error('Error saving player:', error);
throw error;
}
}
// Ship management
async addShipToPlayer(userId, shipData) {
try {
const player = await this.loadPlayer(userId);
if (!player) {
throw new Error('Player not found');
}
const ship = new Ship({
...shipData,
userId,
acquiredAt: new Date()
});
await ship.save();
player.ships.push(ship._id);
await player.save();
logger.info(`Added ship ${ship.name} to player ${userId}`);
return ship;
} catch (error) {
logger.error('Error adding ship to player:', error);
throw error;
}
}
async equipShip(userId, shipId) {
try {
const player = await this.loadPlayer(userId);
if (!player) {
throw new Error('Player not found');
}
const ship = await Ship.findOne({ _id: shipId, userId });
if (!ship) {
throw new Error('Ship not found');
}
// Unequip current ship
if (player.currentShip) {
await Ship.findByIdAndUpdate(player.currentShip, { isEquipped: false });
}
// Equip new ship
ship.isEquipped = true;
await ship.save();
player.currentShip = ship._id;
await player.save();
logger.info(`Equipped ship ${ship.name} for player ${userId}`);
return ship;
} catch (error) {
logger.error('Error equipping ship:', error);
throw error;
}
}
// Server management
async createServer(serverData) {
try {
const serverId = `server_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
const server = {
id: serverId,
...serverData,
createdAt: new Date(),
players: [],
status: 'active'
};
this.servers.set(serverId, server);
logger.info(`Created new server: ${serverId}`);
return server;
} catch (error) {
logger.error('Error creating server:', error);
throw error;
}
}
async joinServer(serverId, userId) {
try {
const server = this.servers.get(serverId);
if (!server) {
throw new Error('Server not found');
}
if (server.players.length >= server.maxPlayers) {
throw new Error('Server is full');
}
if (!server.players.includes(userId)) {
server.players.push(userId);
}
logger.info(`Player ${userId} joined server ${serverId}`);
return server;
} catch (error) {
logger.error('Error joining server:', error);
throw error;
}
}
async leaveServer(serverId, userId) {
try {
const server = this.servers.get(serverId);
if (!server) {
throw new Error('Server not found');
}
server.players = server.players.filter(id => id !== userId);
if (server.players.length === 0) {
this.servers.delete(serverId);
logger.info(`Server ${serverId} deleted (no players)`);
}
logger.info(`Player ${userId} left server ${serverId}`);
return server;
} catch (error) {
logger.error('Error leaving server:', error);
throw error;
}
}
getServerList() {
return Array.from(this.servers.values()).map(server => ({
id: server.id,
name: server.name,
type: server.type,
maxPlayers: server.maxPlayers,
currentPlayers: server.players.length,
status: server.status,
region: server.region,
createdAt: server.createdAt
}));
}
// Game actions
async processGameAction(userId, actionData) {
try {
const player = await this.loadPlayer(userId);
if (!player) {
throw new Error('Player not found');
}
switch (actionData.type) {
case 'dungeon_enter':
return await this.handleDungeonEnter(player, actionData);
case 'ship_upgrade':
return await this.handleShipUpgrade(player, actionData);
case 'item_purchase':
return await this.handleItemPurchase(player, actionData);
case 'daily_reward':
return await this.handleDailyReward(player, actionData);
default:
throw new Error('Unknown action type');
}
} catch (error) {
logger.error('Error processing game action:', error);
throw error;
}
}
async handleDungeonEnter(player, data) {
// Dungeon logic will be implemented here
logger.info(`Player ${player.userId} entering dungeon`);
return { success: true, message: 'Dungeon entered' };
}
async handleShipUpgrade(player, data) {
// Ship upgrade logic will be implemented here
logger.info(`Player ${player.userId} upgrading ship`);
return { success: true, message: 'Ship upgraded' };
}
async handleItemPurchase(player, data) {
// Item purchase logic will be implemented here
logger.info(`Player ${player.userId} purchasing item`);
return { success: true, message: 'Item purchased' };
}
async handleDailyReward(player, data) {
// Daily reward logic will be implemented here
logger.info(`Player ${player.userId} claiming daily reward`);
return { success: true, message: 'Daily reward claimed' };
}
}
// Singleton instance
let gameSystem = null;
async function initializeGameSystems() {
if (!gameSystem) {
gameSystem = new GameSystem();
try {
await gameSystem.initializeGameSystems();
} catch (error) {
logger.error('Failed to initialize game systems:', error);
throw error;
}
}
return gameSystem;
}
function getGameSystem() {
if (!gameSystem) {
logger.warn('Game system not initialized. Call initializeGameSystems() first.');
return null;
}
return gameSystem;
}
module.exports = {
GameSystem,
initializeGameSystems,
getGameSystem
};

119
API/utils/ErrorReporter.js Normal file
View File

@ -0,0 +1,119 @@
/**
* GSO Error Reporter & Analytics (GDD Phase 3 v3.2 lightweight implementation)
* Logs structured errors to file + provides in-memory analytics counters.
* Can be wired to external services (Sentry, Datadog) by replacing _sendToExternal().
*/
const fs = require('fs');
const path = require('path');
class ErrorReporter {
constructor(options = {}) {
this.logDir = options.logDir || path.join(__dirname, '../logs');
this.service = options.service || 'GameServer';
this.env = process.env.NODE_ENV || 'development';
this.counters = {}; // event_type → count
this.errors = []; // last 100 errors in memory
this.maxErrors = 100;
// Ensure logs directory exists
if (!fs.existsSync(this.logDir)) {
fs.mkdirSync(this.logDir, { recursive: true });
}
}
// ── Error capture ──────────────────────────────────────────────────────────
captureError(err, context = {}) {
const entry = {
ts: new Date().toISOString(),
service: this.service,
env: this.env,
message: err?.message || String(err),
stack: err?.stack || null,
context,
};
// Store in memory ring buffer
this.errors.push(entry);
if (this.errors.length > this.maxErrors) this.errors.shift();
// Write to daily log file (non-blocking)
const logFile = path.join(this.logDir, `errors-${new Date().toISOString().slice(0,10)}.log`);
const line = JSON.stringify(entry) + '\n';
fs.appendFile(logFile, line, () => {}); // fire-and-forget
// Increment counter
this.increment('errors.total');
// Hook for external service (Sentry, etc.)
this._sendToExternal(entry);
return entry;
}
// ── Analytics event tracking ───────────────────────────────────────────────
track(event, data = {}) {
this.increment(event);
if (this.env === 'development') {
const logFile = path.join(this.logDir, `analytics-${new Date().toISOString().slice(0,10)}.log`);
fs.appendFile(logFile, JSON.stringify({ ts: new Date().toISOString(), event, data }) + '\n', () => {});
}
}
increment(key) {
this.counters[key] = (this.counters[key] || 0) + 1;
}
// ── Metrics snapshot ───────────────────────────────────────────────────────
getMetrics() {
return {
service: this.service,
uptime: Math.round(process.uptime()),
memoryMB: Math.round(process.memoryUsage().heapUsed / 1048576),
counters: { ...this.counters },
recentErrors: this.errors.slice(-10).map(e => ({ ts: e.ts, message: e.message, context: e.context })),
};
}
// ── Express middleware ─────────────────────────────────────────────────────
requestMiddleware() {
return (req, res, next) => {
const start = Date.now();
this.increment('http.requests');
res.on('finish', () => {
const ms = Date.now() - start;
this.increment(`http.${res.statusCode >= 400 ? 'errors' : 'success'}`);
if (ms > 2000) this.track('http.slow_request', { path: req.path, ms });
});
next();
};
}
errorMiddleware() {
return (err, req, res, next) => {
this.captureError(err, { path: req.path, method: req.method });
res.status(500).json({ error: 'Internal server error' });
};
}
// ── Socket.IO event tracking helper ───────────────────────────────────────
trackSocketEvent(eventName, userId) {
this.increment(`socket.${eventName}`);
this.increment('socket.total');
}
// ── External service stub ──────────────────────────────────────────────────
_sendToExternal(entry) {
// Replace with: Sentry.captureException(new Error(entry.message))
// or: axios.post(process.env.ERROR_WEBHOOK_URL, entry)
// Currently: no-op in development; log to console in production
if (this.env === 'production') {
console.error('[ErrorReporter]', entry.message, entry.context);
}
}
}
// Singleton
const reporter = new ErrorReporter({ service: 'GameServer' });
module.exports = reporter;

File diff suppressed because it is too large Load Diff

View File

@ -1 +1,62 @@
{"_meta":{"lang":"de","name":"de","status":"placeholder - community translation needed"}} {
"_meta": {
"lang": "de",
"name": "Deutsch",
"version": "1.0"
},
"nav": {
"dashboard": "Dashboard",
"dungeons": "Dungeons",
"skills": "Fähigkeiten",
"base": "Basis",
"quests": "Aufgaben",
"inventory": "Inventar",
"crafting": "Herstellung",
"shop": "Laden",
"fleet": "Flotte",
"galaxy": "Galaxie",
"research": "Forschung",
"leaderboard": "Rangliste",
"missions": "Missionen",
"alliance": "Allianz",
"market": "Markt",
"social": "Sozial"
},
"base": {
"buildings": "🏗 Gebäude",
"shipyard": "🚀 Werft",
"starbase": "🌌 Sternenbasis",
"overview": "📊 Übersicht"
},
"resources": {
"metal": "Metall",
"gas": "Gas",
"crystal": "Kristall",
"energyCells": "Energiezellen",
"darkMatter": "Dunkle Materie",
"credits": "Credits",
"gems": "Edelsteine"
},
"actions": {
"build": "Bauen",
"upgrade": "Aufwerten",
"cancel": "Abbrechen",
"collect": "Einsammeln",
"launch": "Starten",
"search": "Suchen",
"join": "Beitreten",
"leave": "Verlassen",
"deposit": "Einzahlen",
"withdraw": "Abheben",
"buy": "Kaufen",
"sell": "Verkaufen"
},
"status": {
"online": "Online",
"offline": "Offline",
"inProgress": "In Arbeit",
"completed": "Abgeschlossen",
"locked": "Gesperrt",
"maxLevel": "Max. Level"
}
}

View File

@ -1 +1,62 @@
{"_meta":{"lang":"es","name":"es","status":"placeholder - community translation needed"}} {
"_meta": {
"lang": "es",
"name": "Español",
"version": "1.0"
},
"nav": {
"dashboard": "Panel",
"dungeons": "Mazmorras",
"skills": "Habilidades",
"base": "Base",
"quests": "Misiones",
"inventory": "Inventario",
"crafting": "Fabricación",
"shop": "Tienda",
"fleet": "Flota",
"galaxy": "Galaxia",
"research": "Investigación",
"leaderboard": "Clasificación",
"missions": "Misiones",
"alliance": "Alianza",
"market": "Mercado",
"social": "Social"
},
"base": {
"buildings": "🏗 Edificios",
"shipyard": "🚀 Astillero",
"starbase": "🌌 Base estelar",
"overview": "📊 Resumen"
},
"resources": {
"metal": "Metal",
"gas": "Gas",
"crystal": "Cristal",
"energyCells": "Células de energía",
"darkMatter": "Materia oscura",
"credits": "Créditos",
"gems": "Gemas"
},
"actions": {
"build": "Construir",
"upgrade": "Mejorar",
"cancel": "Cancelar",
"collect": "Recoger",
"launch": "Lanzar",
"search": "Buscar",
"join": "Unirse",
"leave": "Salir",
"deposit": "Depositar",
"withdraw": "Retirar",
"buy": "Comprar",
"sell": "Vender"
},
"status": {
"online": "En línea",
"offline": "Desconectado",
"inProgress": "En progreso",
"completed": "Completado",
"locked": "Bloqueado",
"maxLevel": "Nivel máx."
}
}

View File

@ -1 +1,62 @@
{"_meta":{"lang":"fr","name":"fr","status":"placeholder - community translation needed"}} {
"_meta": {
"lang": "fr",
"name": "Français",
"version": "1.0"
},
"nav": {
"dashboard": "Tableau de bord",
"dungeons": "Donjons",
"skills": "Compétences",
"base": "Base",
"quests": "Quêtes",
"inventory": "Inventaire",
"crafting": "Artisanat",
"shop": "Boutique",
"fleet": "Flotte",
"galaxy": "Galaxie",
"research": "Recherche",
"leaderboard": "Classement",
"missions": "Missions",
"alliance": "Alliance",
"market": "Marché",
"social": "Social"
},
"base": {
"buildings": "🏗 Bâtiments",
"shipyard": "🚀 Chantier naval",
"starbase": "🌌 Base stellaire",
"overview": "📊 Vue d'ensemble"
},
"resources": {
"metal": "Métal",
"gas": "Gaz",
"crystal": "Cristal",
"energyCells": "Cellules d'énergie",
"darkMatter": "Matière noire",
"credits": "Crédits",
"gems": "Gemmes"
},
"actions": {
"build": "Construire",
"upgrade": "Améliorer",
"cancel": "Annuler",
"collect": "Collecter",
"launch": "Lancer",
"search": "Rechercher",
"join": "Rejoindre",
"leave": "Quitter",
"deposit": "Déposer",
"withdraw": "Retirer",
"buy": "Acheter",
"sell": "Vendre"
},
"status": {
"online": "En ligne",
"offline": "Hors ligne",
"inProgress": "En cours",
"completed": "Terminé",
"locked": "Verrouillé",
"maxLevel": "Niveau max"
}
}

View File

@ -1 +1,62 @@
{"_meta":{"lang":"ja","name":"ja","status":"placeholder - community translation needed"}} {
"_meta": {
"lang": "ja",
"name": "日本語",
"version": "1.0"
},
"nav": {
"dashboard": "ダッシュボード",
"dungeons": "ダンジョン",
"skills": "スキル",
"base": "基地",
"quests": "クエスト",
"inventory": "インベントリ",
"crafting": "クラフト",
"shop": "ショップ",
"fleet": "艦隊",
"galaxy": "銀河",
"research": "研究",
"leaderboard": "ランキング",
"missions": "ミッション",
"alliance": "アライアンス",
"market": "マーケット",
"social": "ソーシャル"
},
"base": {
"buildings": "🏗 建物",
"shipyard": "🚀 造船所",
"starbase": "🌌 星間基地",
"overview": "📊 概要"
},
"resources": {
"metal": "金属",
"gas": "ガス",
"crystal": "クリスタル",
"energyCells": "エネルギーセル",
"darkMatter": "ダークマター",
"credits": "クレジット",
"gems": "ジェム"
},
"actions": {
"build": "建設",
"upgrade": "アップグレード",
"cancel": "キャンセル",
"collect": "収集",
"launch": "発射",
"search": "検索",
"join": "参加",
"leave": "退出",
"deposit": "入金",
"withdraw": "出金",
"buy": "購入",
"sell": "売却"
},
"status": {
"online": "オンライン",
"offline": "オフライン",
"inProgress": "進行中",
"completed": "完了",
"locked": "ロック中",
"maxLevel": "最大レベル"
}
}

View File

@ -1 +1,62 @@
{"_meta":{"lang":"ko","name":"ko","status":"placeholder - community translation needed"}} {
"_meta": {
"lang": "ko",
"name": "한국어",
"version": "1.0"
},
"nav": {
"dashboard": "대시보드",
"dungeons": "던전",
"skills": "스킬",
"base": "기지",
"quests": "퀘스트",
"inventory": "인벤토리",
"crafting": "제작",
"shop": "상점",
"fleet": "함대",
"galaxy": "은하계",
"research": "연구",
"leaderboard": "랭킹",
"missions": "미션",
"alliance": "동맹",
"market": "시장",
"social": "소셜"
},
"base": {
"buildings": "🏗 건물",
"shipyard": "🚀 조선소",
"starbase": "🌌 우주기지",
"overview": "📊 개요"
},
"resources": {
"metal": "금속",
"gas": "가스",
"crystal": "크리스탈",
"energyCells": "에너지 셀",
"darkMatter": "암흑 물질",
"credits": "크레딧",
"gems": "젬"
},
"actions": {
"build": "건설",
"upgrade": "업그레이드",
"cancel": "취소",
"collect": "수집",
"launch": "발사",
"search": "검색",
"join": "참가",
"leave": "나가기",
"deposit": "입금",
"withdraw": "출금",
"buy": "구매",
"sell": "판매"
},
"status": {
"online": "온라인",
"offline": "오프라인",
"inProgress": "진행 중",
"completed": "완료",
"locked": "잠김",
"maxLevel": "최대 레벨"
}
}

View File

@ -1 +1,62 @@
{"_meta":{"lang":"pt","name":"pt","status":"placeholder - community translation needed"}} {
"_meta": {
"lang": "pt",
"name": "Português",
"version": "1.0"
},
"nav": {
"dashboard": "Painel",
"dungeons": "Masmorras",
"skills": "Habilidades",
"base": "Base",
"quests": "Missões",
"inventory": "Inventário",
"crafting": "Criação",
"shop": "Loja",
"fleet": "Frota",
"galaxy": "Galáxia",
"research": "Pesquisa",
"leaderboard": "Classificação",
"missions": "Missões",
"alliance": "Aliança",
"market": "Mercado",
"social": "Social"
},
"base": {
"buildings": "🏗 Edifícios",
"shipyard": "🚀 Estaleiro",
"starbase": "🌌 Base estelar",
"overview": "📊 Visão geral"
},
"resources": {
"metal": "Metal",
"gas": "Gás",
"crystal": "Cristal",
"energyCells": "Células de energia",
"darkMatter": "Matéria escura",
"credits": "Créditos",
"gems": "Gemas"
},
"actions": {
"build": "Construir",
"upgrade": "Melhorar",
"cancel": "Cancelar",
"collect": "Coletar",
"launch": "Lançar",
"search": "Pesquisar",
"join": "Entrar",
"leave": "Sair",
"deposit": "Depositar",
"withdraw": "Retirar",
"buy": "Comprar",
"sell": "Vender"
},
"status": {
"online": "Online",
"offline": "Offline",
"inProgress": "Em andamento",
"completed": "Concluído",
"locked": "Bloqueado",
"maxLevel": "Nível máx."
}
}

View File

@ -1 +1,62 @@
{"_meta":{"lang":"zh","name":"zh","status":"placeholder - community translation needed"}} {
"_meta": {
"lang": "zh",
"name": "中文",
"version": "1.0"
},
"nav": {
"dashboard": "仪表板",
"dungeons": "地下城",
"skills": "技能",
"base": "基地",
"quests": "任务",
"inventory": "背包",
"crafting": "制作",
"shop": "商店",
"fleet": "舰队",
"galaxy": "银河系",
"research": "研究",
"leaderboard": "排行榜",
"missions": "任务",
"alliance": "联盟",
"market": "市场",
"social": "社交"
},
"base": {
"buildings": "🏗 建筑",
"shipyard": "🚀 造船厂",
"starbase": "🌌 星际基地",
"overview": "📊 总览"
},
"resources": {
"metal": "金属",
"gas": "气体",
"crystal": "晶体",
"energyCells": "能量电池",
"darkMatter": "暗物质",
"credits": "积分",
"gems": "宝石"
},
"actions": {
"build": "建造",
"upgrade": "升级",
"cancel": "取消",
"collect": "收集",
"launch": "发射",
"search": "搜索",
"join": "加入",
"leave": "离开",
"deposit": "存入",
"withdraw": "提取",
"buy": "购买",
"sell": "出售"
},
"status": {
"online": "在线",
"offline": "离线",
"inProgress": "进行中",
"completed": "已完成",
"locked": "已锁定",
"maxLevel": "最高等级"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 254 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 226 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 213 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 291 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 324 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 312 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 286 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 214 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 200 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 188 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 185 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 KiB

View File

@ -0,0 +1,28 @@
{
"version": "1.0",
"tiers": [
{
"tier": 1,
"techs": [
{ "id": "alliance_storage_1", "name": "Expanded Warehouse I", "desc": "Increase alliance warehouse cap by 10,000 per resource.", "cost": {"credits":5000,"metal":2000}, "effect": {"warehouseCap":10000}, "prereq": [], "icon": "fa-warehouse", "maxLevel": 3 },
{ "id": "alliance_xp_1", "name": "Shared Knowledge I", "desc": "+5% XP for all members.", "cost": {"credits":8000,"crystal":500}, "effect": {"memberXpBonus":0.05}, "prereq": [], "icon": "fa-graduation-cap", "maxLevel": 3 },
{ "id": "alliance_credits_1", "name": "Trade Network I", "desc": "Reduce market listing fee by 0.5% for all members.", "cost": {"credits":6000,"gas":1000}, "effect": {"marketFeeReduction":0.005}, "prereq": [], "icon": "fa-coins", "maxLevel": 2 }
]
},
{
"tier": 2,
"techs": [
{ "id": "alliance_storage_2", "name": "Expanded Warehouse II", "desc": "Increase warehouse cap by an additional 25,000.", "cost": {"credits":15000,"metal":8000}, "effect": {"warehouseCap":25000}, "prereq": ["alliance_storage_1"], "icon": "fa-warehouse", "maxLevel": 1 },
{ "id": "alliance_craft_1", "name": "Collective Crafting", "desc": "All members gain -10% craft time.", "cost": {"credits":12000,"crystal":1500},"effect": {"craftTimeReduction":0.10}, "prereq": ["alliance_xp_1"], "icon": "fa-hammer", "maxLevel": 2 },
{ "id": "alliance_defense_1", "name": "Defensive Grid I", "desc": "+10% PvP defense for all members.", "cost": {"credits":10000,"metal":5000}, "effect": {"pvpDefenseBonus":0.10}, "prereq": ["alliance_credits_1"],"icon": "fa-shield-alt", "maxLevel": 3 }
]
},
{
"tier": 3,
"techs": [
{ "id": "alliance_dm_1", "name": "Void Tap", "desc": "+15% dark matter production for all members.", "cost": {"credits":25000,"darkMatter":50},"effect": {"darkMatterBonus":0.15}, "prereq": ["alliance_storage_2","alliance_craft_1"], "icon": "fa-atom", "maxLevel": 1 },
{ "id": "alliance_fleet_1", "name": "Fleet Coordination", "desc": "+20% fleet mission rewards for all members.", "cost": {"credits":20000,"gas":5000}, "effect": {"fleetRewardBonus":0.20}, "prereq": ["alliance_defense_1"],"icon": "fa-fighter-jet","maxLevel": 2 }
]
}
]
}

View File

@ -1,97 +0,0 @@
[
{
"id": "pirate_lair",
"name": "Pirate Lair",
"description": "Dangerous pirate hideouts with valuable loot",
"difficulty": "easy",
"minLevel": 1,
"maxPlayers": 4,
"roomCount": [4, 6],
"energyCost": 15,
"rewardMultiplier": 1.0,
"enemyPool": ["space_pirate", "pirate_captain", "defense_turret"],
"lootTable": [
{ "itemId": "iron_ore", "weight": 40, "qtyMin": 1, "qtyMax": 5 },
{ "itemId": "copper_ore", "weight": 30, "qtyMin": 1, "qtyMax": 3 },
{ "itemId": "bandage", "weight": 20, "qtyMin": 1, "qtyMax": 2 },
{ "itemId": "pistol_standard_common", "weight": 10, "qtyMin": 1, "qtyMax": 1 }
],
"ui": { "icon": "fa-skull-crossbones", "color": "#e67e22" }
},
{
"id": "asteroid_mine",
"name": "Asteroid Mine",
"description": "Abandoned mining facilities rich in ore deposits",
"difficulty": "easy",
"minLevel": 2,
"maxPlayers": 4,
"roomCount": [4, 7],
"energyCost": 10,
"rewardMultiplier": 0.8,
"enemyPool": ["mining_drone", "rock_creature", "explosive_asteroid"],
"lootTable": [
{ "itemId": "iron_ore", "weight": 35, "qtyMin": 2, "qtyMax": 8 },
{ "itemId": "copper_ore", "weight": 30, "qtyMin": 1, "qtyMax": 6 },
{ "itemId": "titanium_ore", "weight": 20, "qtyMin": 1, "qtyMax": 3 },
{ "itemId": "gold_ore", "weight": 15, "qtyMin": 1, "qtyMax": 2 }
],
"ui": { "icon": "fa-meteor", "color": "#95a5a6" }
},
{
"id": "alien_ruins",
"name": "Alien Ruins",
"description": "Ancient alien structures filled with mysterious technology",
"difficulty": "medium",
"minLevel": 3,
"maxPlayers": 4,
"roomCount": [5, 8],
"energyCost": 20,
"rewardMultiplier": 1.2,
"enemyPool": ["alien_guardian", "ancient_drone", "crystal_golem"],
"lootTable": [
{ "itemId": "flux_crystal", "weight": 30, "qtyMin": 1, "qtyMax": 3 },
{ "itemId": "alien_fauna_sample", "weight": 25, "qtyMin": 1, "qtyMax": 2 },
{ "itemId": "basic_circuit", "weight": 25, "qtyMin": 1, "qtyMax": 2 },
{ "itemId": "assault_rifle_common", "weight": 20, "qtyMin": 1, "qtyMax": 1 }
],
"ui": { "icon": "fa-monument", "color": "#8e44ad" }
},
{
"id": "corrupted_vault",
"name": "Corrupted AI Vault",
"description": "Malfunctioning AI facilities with corrupted security systems",
"difficulty": "hard",
"minLevel": 5,
"maxPlayers": 4,
"roomCount": [6, 9],
"energyCost": 25,
"rewardMultiplier": 1.5,
"enemyPool": ["security_drone", "corrupted_ai", "virus_program"],
"lootTable": [
{ "itemId": "logic_circuit", "weight": 30, "qtyMin": 1, "qtyMax": 3 },
{ "itemId": "power_circuit", "weight": 25, "qtyMin": 1, "qtyMax": 2 },
{ "itemId": "control_circuit", "weight": 25, "qtyMin": 1, "qtyMax": 2 },
{ "itemId": "sniper_rare", "weight": 20, "qtyMin": 1, "qtyMax": 1 }
],
"ui": { "icon": "fa-robot", "color": "#e74c3c" }
},
{
"id": "nebula_anomaly",
"name": "Nebula Anomaly",
"description": "Strange energy anomalies in the deep void of space",
"difficulty": "extreme",
"minLevel": 8,
"maxPlayers": 4,
"roomCount": [7, 10],
"energyCost": 30,
"rewardMultiplier": 2.0,
"enemyPool": ["energy_being", "phase_shifter", "quantum_entity"],
"lootTable": [
{ "itemId": "quantum_circuit", "weight": 25, "qtyMin": 1, "qtyMax": 2 },
{ "itemId": "void_crystal", "weight": 25, "qtyMin": 1, "qtyMax": 2 },
{ "itemId": "phase_crystal", "weight": 25, "qtyMin": 1, "qtyMax": 2 },
{ "itemId": "plasma_cutter_epic", "weight": 25, "qtyMin": 1, "qtyMax": 1 }
],
"ui": { "icon": "fa-star", "color": "#2980b9" }
}
]

View File

@ -1,15 +0,0 @@
[
{ "id": "space_pirate", "name": "Space Pirate", "health": 25, "attack": 10, "defense": 3, "speed": 8, "experience": 15, "credits": 12, "rarity": "common" },
{ "id": "pirate_captain", "name": "Pirate Captain", "health": 40, "attack": 15, "defense": 6, "speed": 12, "experience": 30, "credits": 20, "rarity": "uncommon" },
{ "id": "defense_turret", "name": "Defense Turret", "health": 35, "attack": 14, "defense": 8, "speed": 0, "experience": 20, "credits": 15, "rarity": "common" },
{ "id": "mining_drone", "name": "Mining Drone", "health": 20, "attack": 8, "defense": 3, "speed": 5, "experience": 12, "credits": 8, "rarity": "common" },
{ "id": "rock_creature", "name": "Rock Creature", "health": 45, "attack": 6, "defense": 12, "speed": 3, "experience": 18, "credits": 10, "rarity": "common" },
{ "id": "alien_guardian", "name": "Alien Guardian", "health": 50, "attack": 8, "defense": 5, "speed": 6, "experience": 25, "credits": 15, "rarity": "common" },
{ "id": "ancient_drone", "name": "Ancient Drone", "health": 30, "attack": 12, "defense": 2, "speed": 10, "experience": 20, "credits": 10, "rarity": "uncommon" },
{ "id": "crystal_golem", "name": "Crystal Golem", "health": 80, "attack": 6, "defense": 10, "speed": 4, "experience": 35, "credits": 25, "rarity": "rare" },
{ "id": "security_drone", "name": "Security Drone", "health": 35, "attack": 14, "defense": 4, "speed": 10, "experience": 22, "credits": 15, "rarity": "uncommon" },
{ "id": "corrupted_ai", "name": "Corrupted AI", "health": 60, "attack": 20, "defense": 2, "speed": 15, "experience": 40, "credits": 30, "rarity": "rare" },
{ "id": "energy_being", "name": "Energy Being", "health": 55, "attack": 22, "defense": 3, "speed": 18, "experience": 45, "credits": 35, "rarity": "epic" },
{ "id": "phase_shifter", "name": "Phase Shifter", "health": 50, "attack": 25, "defense": 5, "speed": 20, "experience": 50, "credits": 40, "rarity": "epic" },
{ "id": "quantum_entity", "name": "Quantum Entity", "health": 70, "attack": 35, "defense": 5, "speed": 20, "experience": 60, "credits": 50, "rarity": "legendary" }
]

View File

@ -1,14 +0,0 @@
{
"templates": {
"armour": {
"id": "backpack_basic_common",
"texture": "assets/gso/textures/armour/backpack/backpack_basic_common.png",
"stats": {
"health": 20,
"resistance": 0.03,
"defenceRating": 1,
"reflectChance": 0.0
}
}
}
}

View File

@ -1,14 +0,0 @@
{
"templates": {
"armour": {
"id": "backpack_field_rare",
"texture": "assets/gso/textures/armour/backpack/backpack_field_rare.png",
"stats": {
"health": 40,
"resistance": 0.08,
"defenceRating": 3,
"reflectChance": 0.01
}
}
}
}

View File

@ -1,14 +0,0 @@
{
"templates": {
"armour": {
"id": "backpack_reactor_epic",
"texture": "assets/gso/textures/armour/backpack/backpack_reactor_epic.png",
"stats": {
"health": 70,
"resistance": 0.15,
"defenceRating": 6,
"reflectChance": 0.03
}
}
}
}

View File

@ -1,14 +0,0 @@
{
"templates": {
"armour": {
"id": "body_basic_common",
"texture": "assets/gso/textures/armour/body/body_basic_common.png",
"stats": {
"health": 60,
"resistance": 0.1,
"defenceRating": 4,
"reflectChance": 0.0
}
}
}
}

View File

@ -1,14 +0,0 @@
{
"templates": {
"armour": {
"id": "body_exosuit_epic",
"texture": "assets/gso/textures/armour/body/body_exosuit_epic.png",
"stats": {
"health": 180,
"resistance": 0.3,
"defenceRating": 14,
"reflectChance": 0.05
}
}
}
}

View File

@ -1,14 +0,0 @@
{
"templates": {
"armour": {
"id": "body_plated_rare",
"texture": "assets/gso/textures/armour/body/body_plated_rare.png",
"stats": {
"health": 110,
"resistance": 0.2,
"defenceRating": 8,
"reflectChance": 0.02
}
}
}
}

View File

@ -1,14 +0,0 @@
{
"templates": {
"armour": {
"id": "boots_assault_rare",
"texture": "assets/gso/textures/armour/boots/boots_assault_rare.png",
"stats": {
"health": 40,
"resistance": 0.12,
"defenceRating": 4,
"reflectChance": 0.01
}
}
}
}

View File

@ -1,14 +0,0 @@
{
"templates": {
"armour": {
"id": "boots_basic_common",
"texture": "assets/gso/textures/armour/boots/boots_basic_common.png",
"stats": {
"health": 20,
"resistance": 0.05,
"defenceRating": 2,
"reflectChance": 0.0
}
}
}
}

View File

@ -1,14 +0,0 @@
{
"templates": {
"armour": {
"id": "boots_gravity_epic",
"texture": "assets/gso/textures/armour/boots/boots_gravity_epic.png",
"stats": {
"health": 65,
"resistance": 0.2,
"defenceRating": 7,
"reflectChance": 0.025
}
}
}
}

View File

@ -1,14 +0,0 @@
{
"templates": {
"armour": {
"id": "hands_basic_common",
"texture": "assets/gso/textures/armour/hands/hands_basic_common.png",
"stats": {
"health": 15,
"resistance": 0.04,
"defenceRating": 1,
"reflectChance": 0.0
}
}
}
}

View File

@ -1,14 +0,0 @@
{
"templates": {
"armour": {
"id": "hands_combat_rare",
"texture": "assets/gso/textures/armour/hands/hands_combat_rare.png",
"stats": {
"health": 30,
"resistance": 0.1,
"defenceRating": 3,
"reflectChance": 0.01
}
}
}
}

View File

@ -1,14 +0,0 @@
{
"templates": {
"armour": {
"id": "hands_elite_epic",
"texture": "assets/gso/textures/armour/hands/hands_elite_epic.png",
"stats": {
"health": 50,
"resistance": 0.18,
"defenceRating": 6,
"reflectChance": 0.025
}
}
}
}

View File

@ -1,14 +0,0 @@
{
"templates": {
"armour": {
"id": "helmet_basic_common",
"texture": "assets/gso/textures/armour/helmet/helmet_basic_common.png",
"stats": {
"health": 25,
"resistance": 0.05,
"defenceRating": 2,
"reflectChance": 0.0
}
}
}
}

View File

@ -1,14 +0,0 @@
{
"templates": {
"armour": {
"id": "helmet_reinforced_rare",
"texture": "assets/gso/textures/armour/helmet/helmet_reinforced_rare.png",
"stats": {
"health": 45,
"resistance": 0.12,
"defenceRating": 5,
"reflectChance": 0.01
}
}
}
}

View File

@ -1,14 +0,0 @@
{
"templates": {
"armour": {
"id": "helmet_tactical_epic",
"texture": "assets/gso/textures/armour/helmet/helmet_tactical_epic.png",
"stats": {
"health": 70,
"resistance": 0.2,
"defenceRating": 8,
"reflectChance": 0.03
}
}
}
}

View File

@ -1,14 +0,0 @@
{
"templates": {
"armour": {
"id": "pants_basic_common",
"texture": "assets/gso/textures/armour/pants/pants_basic_common.png",
"stats": {
"health": 30,
"resistance": 0.06,
"defenceRating": 2,
"reflectChance": 0.0
}
}
}
}

View File

@ -1,14 +0,0 @@
{
"templates": {
"armour": {
"id": "pants_exo_epic",
"texture": "assets/gso/textures/armour/pants/pants_exo_epic.png",
"stats": {
"health": 85,
"resistance": 0.22,
"defenceRating": 9,
"reflectChance": 0.03
}
}
}
}

View File

@ -1,14 +0,0 @@
{
"templates": {
"armour": {
"id": "pants_reinforced_rare",
"texture": "assets/gso/textures/armour/pants/pants_reinforced_rare.png",
"stats": {
"health": 55,
"resistance": 0.14,
"defenceRating": 5,
"reflectChance": 0.015
}
}
}
}

View File

@ -0,0 +1,28 @@
{
"templates": {
"armour": {
"id": "backpack_field_rare",
"texture": "assets/gso/textures/armour/backpack/backpack_field_rare.png",
"stats": {
"health": 40,
"resistance": 0.08,
"defenceRating": 3,
"reflectChance": 0.01
},
"name": "Backpack Field Rare",
"type": "armour",
"rarity": "rare",
"price": 3000,
"currency": "credits",
"description": "Backpack Field Rare.",
"categories": [
"shop",
"dungeon_loot"
],
"requirements": {
"level": 5
},
"stackable": false
}
}
}

View File

@ -0,0 +1,28 @@
{
"templates": {
"armour": {
"id": "backpack_reactor_epic",
"texture": "assets/gso/textures/armour/backpack/backpack_reactor_epic.png",
"stats": {
"health": 70,
"resistance": 0.15,
"defenceRating": 6,
"reflectChance": 0.03
},
"name": "Backpack Reactor Epic",
"type": "armour",
"rarity": "epic",
"price": 8000,
"currency": "credits",
"description": "Backpack Reactor Epic.",
"categories": [
"shop",
"dungeon_loot"
],
"requirements": {
"level": 10
},
"stackable": false
}
}
}

View File

@ -0,0 +1,28 @@
{
"templates": {
"armour": {
"id": "boots_assault_rare",
"texture": "assets/gso/textures/armour/boots/boots_assault_rare.png",
"stats": {
"health": 40,
"resistance": 0.12,
"defenceRating": 4,
"reflectChance": 0.01
},
"name": "Boots Assault Rare",
"type": "armour",
"rarity": "rare",
"price": 3000,
"currency": "credits",
"description": "Boots Assault Rare.",
"categories": [
"shop",
"dungeon_loot"
],
"requirements": {
"level": 5
},
"stackable": false
}
}
}

View File

@ -0,0 +1,28 @@
{
"templates": {
"armour": {
"id": "boots_gravity_epic",
"texture": "assets/gso/textures/armour/boots/boots_gravity_epic.png",
"stats": {
"health": 65,
"resistance": 0.2,
"defenceRating": 7,
"reflectChance": 0.025
},
"name": "Boots Gravity Epic",
"type": "armour",
"rarity": "epic",
"price": 8000,
"currency": "credits",
"description": "Boots Gravity Epic.",
"categories": [
"shop",
"dungeon_loot"
],
"requirements": {
"level": 10
},
"stackable": false
}
}
}

View File

@ -0,0 +1,28 @@
{
"templates": {
"armour": {
"id": "hands_basic_common",
"texture": "assets/gso/textures/armour/hands/hands_basic_common.png",
"stats": {
"health": 15,
"resistance": 0.04,
"defenceRating": 1,
"reflectChance": 0.0
},
"name": "Hands Basic Common",
"type": "armour",
"rarity": "common",
"price": 1000,
"currency": "credits",
"description": "Hands Basic Common.",
"categories": [
"shop",
"dungeon_loot"
],
"requirements": {
"level": 1
},
"stackable": false
}
}
}

View File

@ -0,0 +1,28 @@
{
"templates": {
"armour": {
"id": "hands_combat_rare",
"texture": "assets/gso/textures/armour/hands/hands_combat_rare.png",
"stats": {
"health": 30,
"resistance": 0.1,
"defenceRating": 3,
"reflectChance": 0.01
},
"name": "Hands Combat Rare",
"type": "armour",
"rarity": "rare",
"price": 3000,
"currency": "credits",
"description": "Hands Combat Rare.",
"categories": [
"shop",
"dungeon_loot"
],
"requirements": {
"level": 5
},
"stackable": false
}
}
}

View File

@ -0,0 +1,28 @@
{
"templates": {
"armour": {
"id": "hands_elite_epic",
"texture": "assets/gso/textures/armour/hands/hands_elite_epic.png",
"stats": {
"health": 50,
"resistance": 0.18,
"defenceRating": 6,
"reflectChance": 0.025
},
"name": "Hands Elite Epic",
"type": "armour",
"rarity": "epic",
"price": 8000,
"currency": "credits",
"description": "Hands Elite Epic.",
"categories": [
"shop",
"dungeon_loot"
],
"requirements": {
"level": 10
},
"stackable": false
}
}
}

View File

@ -0,0 +1,28 @@
{
"templates": {
"armour": {
"id": "helmet_tactical_epic",
"texture": "assets/gso/textures/armour/helmet/helmet_tactical_epic.png",
"stats": {
"health": 70,
"resistance": 0.2,
"defenceRating": 8,
"reflectChance": 0.03
},
"name": "Helmet Tactical Epic",
"type": "armour",
"rarity": "epic",
"price": 8000,
"currency": "credits",
"description": "Helmet Tactical Epic.",
"categories": [
"shop",
"dungeon_loot"
],
"requirements": {
"level": 10
},
"stackable": false
}
}
}

View File

@ -0,0 +1,28 @@
{
"templates": {
"armour": {
"id": "pants_exo_epic",
"texture": "assets/gso/textures/armour/pants/pants_exo_epic.png",
"stats": {
"health": 85,
"resistance": 0.22,
"defenceRating": 9,
"reflectChance": 0.03
},
"name": "Pants Exo Epic",
"type": "armour",
"rarity": "epic",
"price": 8000,
"currency": "credits",
"description": "Pants Exo Epic.",
"categories": [
"shop",
"dungeon_loot"
],
"requirements": {
"level": 10
},
"stackable": false
}
}
}

View File

@ -0,0 +1,28 @@
{
"templates": {
"armour": {
"id": "pants_reinforced_rare",
"texture": "assets/gso/textures/armour/pants/pants_reinforced_rare.png",
"stats": {
"health": 55,
"resistance": 0.14,
"defenceRating": 5,
"reflectChance": 0.015
},
"name": "Pants Reinforced Rare",
"type": "armour",
"rarity": "rare",
"price": 3000,
"currency": "credits",
"description": "Pants Reinforced Rare.",
"categories": [
"shop",
"dungeon_loot"
],
"requirements": {
"level": 5
},
"stackable": false
}
}
}

View File

@ -8,6 +8,20 @@
"resistance": 0.0, "resistance": 0.0,
"defenceRating": 0, "defenceRating": 0,
"reflectChance": 0.0 "reflectChance": 0.0
},
"name": "Ballistic Alloy Common",
"type": "hullPlating",
"rarity": "common",
"price": 500,
"currency": "credits",
"description": "Ballistic Alloy Common.",
"categories": [
"shop",
"dungeon_loot"
],
"stackable": true,
"requirements": {
"level": 1
} }
} }
} }

View File

@ -8,6 +8,20 @@
"resistance": 0.0, "resistance": 0.0,
"defenceRating": 0, "defenceRating": 0,
"reflectChance": 0.0 "reflectChance": 0.0
},
"name": "Carbon Titanium Composite Common",
"type": "hullPlating",
"rarity": "common",
"price": 500,
"currency": "credits",
"description": "Carbon Titanium Composite Common.",
"categories": [
"shop",
"dungeon_loot"
],
"stackable": true,
"requirements": {
"level": 1
} }
} }
} }

View File

@ -8,6 +8,20 @@
"resistance": 0.0, "resistance": 0.0,
"defenceRating": 0, "defenceRating": 0,
"reflectChance": 0.0 "reflectChance": 0.0
},
"name": "Chrono Alloy Common",
"type": "hullPlating",
"rarity": "common",
"price": 500,
"currency": "credits",
"description": "Chrono Alloy Common.",
"categories": [
"shop",
"dungeon_loot"
],
"stackable": true,
"requirements": {
"level": 1
} }
} }
} }

View File

@ -8,6 +8,20 @@
"resistance": 0.0, "resistance": 0.0,
"defenceRating": 0, "defenceRating": 0,
"reflectChance": 0.0 "reflectChance": 0.0
},
"name": "Dimensional Alloy Common",
"type": "hullPlating",
"rarity": "common",
"price": 500,
"currency": "credits",
"description": "Dimensional Alloy Common.",
"categories": [
"shop",
"dungeon_loot"
],
"stackable": true,
"requirements": {
"level": 1
} }
} }
} }

View File

@ -8,6 +8,20 @@
"resistance": 0.0, "resistance": 0.0,
"defenceRating": 0, "defenceRating": 0,
"reflectChance": 0.0 "reflectChance": 0.0
},
"name": "Flux Core Alloy Common",
"type": "hullPlating",
"rarity": "common",
"price": 500,
"currency": "credits",
"description": "Flux Core Alloy Common.",
"categories": [
"shop",
"dungeon_loot"
],
"stackable": true,
"requirements": {
"level": 1
} }
} }
} }

View File

@ -8,6 +8,20 @@
"resistance": 0.0, "resistance": 0.0,
"defenceRating": 0, "defenceRating": 0,
"reflectChance": 0.0 "reflectChance": 0.0
},
"name": "Neutronium Composite Common",
"type": "hullPlating",
"rarity": "common",
"price": 500,
"currency": "credits",
"description": "Neutronium Composite Common.",
"categories": [
"shop",
"dungeon_loot"
],
"stackable": true,
"requirements": {
"level": 1
} }
} }
} }

View File

@ -8,6 +8,20 @@
"resistance": 0.0, "resistance": 0.0,
"defenceRating": 0, "defenceRating": 0,
"reflectChance": 0.0 "reflectChance": 0.0
},
"name": "Phase Alloy Common",
"type": "hullPlating",
"rarity": "common",
"price": 500,
"currency": "credits",
"description": "Phase Alloy Common.",
"categories": [
"shop",
"dungeon_loot"
],
"stackable": true,
"requirements": {
"level": 1
} }
} }
} }

View File

@ -8,6 +8,20 @@
"resistance": 0.0, "resistance": 0.0,
"defenceRating": 0, "defenceRating": 0,
"reflectChance": 0.0 "reflectChance": 0.0
},
"name": "Plasma Channel Alloy Common",
"type": "hullPlating",
"rarity": "common",
"price": 500,
"currency": "credits",
"description": "Plasma Channel Alloy Common.",
"categories": [
"shop",
"dungeon_loot"
],
"stackable": true,
"requirements": {
"level": 1
} }
} }
} }

View File

@ -8,6 +8,20 @@
"resistance": 0.0, "resistance": 0.0,
"defenceRating": 0, "defenceRating": 0,
"reflectChance": 0.0 "reflectChance": 0.0
},
"name": "Reinforced Steel Common",
"type": "hullPlating",
"rarity": "common",
"price": 500,
"currency": "credits",
"description": "Reinforced Steel Common.",
"categories": [
"shop",
"dungeon_loot"
],
"stackable": true,
"requirements": {
"level": 1
} }
} }
} }

View File

@ -8,6 +8,20 @@
"resistance": 0.0, "resistance": 0.0,
"defenceRating": 0, "defenceRating": 0,
"reflectChance": 0.0 "reflectChance": 0.0
},
"name": "Superconductive Alloy Common",
"type": "hullPlating",
"rarity": "common",
"price": 500,
"currency": "credits",
"description": "Superconductive Alloy Common.",
"categories": [
"shop",
"dungeon_loot"
],
"stackable": true,
"requirements": {
"level": 1
} }
} }
} }

View File

@ -8,6 +8,20 @@
"resistance": 0.0, "resistance": 0.0,
"defenceRating": 0, "defenceRating": 0,
"reflectChance": 0.0 "reflectChance": 0.0
},
"name": "Voidsteel Common",
"type": "hullPlating",
"rarity": "common",
"price": 500,
"currency": "credits",
"description": "Voidsteel Common.",
"categories": [
"shop",
"dungeon_loot"
],
"stackable": true,
"requirements": {
"level": 1
} }
} }
} }

View File

@ -8,6 +8,20 @@
"resistance": 0.0, "resistance": 0.0,
"defenceRating": 0, "defenceRating": 0,
"reflectChance": 0.0 "reflectChance": 0.0
},
"name": "Ablative Plating Common",
"type": "hullPlating",
"rarity": "common",
"price": 500,
"currency": "credits",
"description": "Ablative Plating Common.",
"categories": [
"shop",
"dungeon_loot"
],
"stackable": true,
"requirements": {
"level": 1
} }
} }
} }

View File

@ -8,6 +8,20 @@
"resistance": 0.0, "resistance": 0.0,
"defenceRating": 0, "defenceRating": 0,
"reflectChance": 0.0 "reflectChance": 0.0
},
"name": "Advanced Hull Section Common",
"type": "hullPlating",
"rarity": "common",
"price": 500,
"currency": "credits",
"description": "Advanced Hull Section Common.",
"categories": [
"shop",
"dungeon_loot"
],
"stackable": true,
"requirements": {
"level": 1
} }
} }
} }

View File

@ -8,6 +8,20 @@
"resistance": 0.0, "resistance": 0.0,
"defenceRating": 0, "defenceRating": 0,
"reflectChance": 0.0 "reflectChance": 0.0
},
"name": "Armor Hull Section Common",
"type": "hullPlating",
"rarity": "common",
"price": 500,
"currency": "credits",
"description": "Armor Hull Section Common.",
"categories": [
"shop",
"dungeon_loot"
],
"stackable": true,
"requirements": {
"level": 1
} }
} }
} }

View File

@ -8,6 +8,20 @@
"resistance": 0.0, "resistance": 0.0,
"defenceRating": 0, "defenceRating": 0,
"reflectChance": 0.0 "reflectChance": 0.0
},
"name": "Exotic Hull Section Common",
"type": "hullPlating",
"rarity": "common",
"price": 500,
"currency": "credits",
"description": "Exotic Hull Section Common.",
"categories": [
"shop",
"dungeon_loot"
],
"stackable": true,
"requirements": {
"level": 1
} }
} }
} }

View File

@ -8,6 +8,20 @@
"resistance": 0.0, "resistance": 0.0,
"defenceRating": 0, "defenceRating": 0,
"reflectChance": 0.0 "reflectChance": 0.0
},
"name": "Heavy Hull Section Common",
"type": "hullPlating",
"rarity": "common",
"price": 500,
"currency": "credits",
"description": "Heavy Hull Section Common.",
"categories": [
"shop",
"dungeon_loot"
],
"stackable": true,
"requirements": {
"level": 1
} }
} }
} }

View File

@ -8,6 +8,20 @@
"resistance": 0.0, "resistance": 0.0,
"defenceRating": 0, "defenceRating": 0,
"reflectChance": 0.0 "reflectChance": 0.0
},
"name": "Light Hull Section Common",
"type": "hullPlating",
"rarity": "common",
"price": 500,
"currency": "credits",
"description": "Light Hull Section Common.",
"categories": [
"shop",
"dungeon_loot"
],
"stackable": true,
"requirements": {
"level": 1
} }
} }
} }

View File

@ -8,6 +8,20 @@
"resistance": 0.0, "resistance": 0.0,
"defenceRating": 0, "defenceRating": 0,
"reflectChance": 0.0 "reflectChance": 0.0
},
"name": "Standard Hull Section Common",
"type": "hullPlating",
"rarity": "common",
"price": 500,
"currency": "credits",
"description": "Standard Hull Section Common.",
"categories": [
"shop",
"dungeon_loot"
],
"stackable": true,
"requirements": {
"level": 1
} }
} }
} }

View File

@ -6,6 +6,20 @@
"stats": [], "stats": [],
"meta": { "meta": {
"materialCategory": "bio" "materialCategory": "bio"
},
"name": "Bio Pulp Common",
"type": "materials",
"rarity": "common",
"price": 500,
"currency": "credits",
"description": "Bio Pulp Common.",
"categories": [
"shop",
"dungeon_loot"
],
"stackable": true,
"requirements": {
"level": 1
} }
} }
} }

View File

@ -6,6 +6,20 @@
"stats": [], "stats": [],
"meta": { "meta": {
"materialCategory": "bio" "materialCategory": "bio"
},
"name": "Organic Insulation Common",
"type": "materials",
"rarity": "common",
"price": 500,
"currency": "credits",
"description": "Organic Insulation Common.",
"categories": [
"shop",
"dungeon_loot"
],
"stackable": true,
"requirements": {
"level": 1
} }
} }
} }

View File

@ -6,6 +6,20 @@
"stats": [], "stats": [],
"meta": { "meta": {
"materialCategory": "bio" "materialCategory": "bio"
},
"name": "Plant Matter Common",
"type": "materials",
"rarity": "common",
"price": 500,
"currency": "credits",
"description": "Plant Matter Common.",
"categories": [
"shop",
"dungeon_loot"
],
"stackable": true,
"requirements": {
"level": 1
} }
} }
} }

View File

@ -6,6 +6,20 @@
"stats": [], "stats": [],
"meta": { "meta": {
"materialCategory": "chemical" "materialCategory": "chemical"
},
"name": "Aluminum Alloy Common",
"type": "materials",
"rarity": "common",
"price": 500,
"currency": "credits",
"description": "Aluminum Alloy Common.",
"categories": [
"shop",
"dungeon_loot"
],
"stackable": true,
"requirements": {
"level": 1
} }
} }
} }

View File

@ -6,6 +6,20 @@
"stats": [], "stats": [],
"meta": { "meta": {
"materialCategory": "chemical" "materialCategory": "chemical"
},
"name": "Bio Composite Material Common",
"type": "materials",
"rarity": "common",
"price": 500,
"currency": "credits",
"description": "Bio Composite Material Common.",
"categories": [
"shop",
"dungeon_loot"
],
"stackable": true,
"requirements": {
"level": 1
} }
} }
} }

View File

@ -6,6 +6,20 @@
"stats": [], "stats": [],
"meta": { "meta": {
"materialCategory": "chemical" "materialCategory": "chemical"
},
"name": "Carbon Nanotube Alloy Common",
"type": "materials",
"rarity": "common",
"price": 500,
"currency": "credits",
"description": "Carbon Nanotube Alloy Common.",
"categories": [
"shop",
"dungeon_loot"
],
"stackable": true,
"requirements": {
"level": 1
} }
} }
} }

Some files were not shown because too many files have changed in this diff Show More