Shatteredvoid/src/database/migrations/001_initial_system_tables.js
MegaProxy d41d1e8125 feat: implement complete Phase 2 frontend foundation with React 18
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>
2025-08-02 18:36:06 +00:00

192 lines
7.3 KiB
JavaScript

exports.up = async function (knex) {
// System configuration with hot-reloading support
await knex.schema.createTable('system_config', (table) => {
table.increments('id').primary();
table.string('config_key', 100).unique().notNullable();
table.jsonb('config_value').notNullable();
table.string('config_type', 20).notNullable().checkIn(['string', 'number', 'boolean', 'json', 'array']);
table.text('description');
table.boolean('requires_restart').defaultTo(false);
table.boolean('is_public').defaultTo(false); // Can be exposed to client
table.timestamp('created_at').defaultTo(knex.fn.now());
table.timestamp('updated_at').defaultTo(knex.fn.now());
table.integer('updated_by'); // Will reference admin_users(id) after table creation
});
// Game tick system with user grouping
await knex.schema.createTable('game_tick_config', (table) => {
table.increments('id').primary();
table.integer('tick_interval_ms').notNullable().defaultTo(60000);
table.integer('user_groups_count').notNullable().defaultTo(10);
table.integer('max_retry_attempts').notNullable().defaultTo(5);
table.integer('bonus_tick_threshold').notNullable().defaultTo(3);
table.boolean('is_active').defaultTo(true);
table.timestamp('created_at').defaultTo(knex.fn.now());
table.timestamp('updated_at').defaultTo(knex.fn.now());
});
await knex.schema.createTable('game_tick_log', (table) => {
table.bigIncrements('id').primary();
table.bigInteger('tick_number').notNullable();
table.integer('user_group').notNullable();
table.timestamp('started_at').notNullable();
table.timestamp('completed_at');
table.string('status', 20).notNullable().checkIn(['running', 'completed', 'failed', 'retrying']);
table.integer('retry_count').defaultTo(0);
table.text('error_message');
table.integer('processed_players').defaultTo(0);
table.jsonb('performance_metrics');
table.timestamp('created_at').defaultTo(knex.fn.now());
table.index(['tick_number']);
table.index(['user_group']);
table.index(['status']);
});
// Event system configuration
await knex.schema.createTable('event_types', (table) => {
table.increments('id').primary();
table.string('name', 100).unique().notNullable();
table.text('description');
table.string('trigger_type', 20).notNullable().checkIn(['admin', 'player', 'system', 'mixed']);
table.boolean('is_active').defaultTo(true);
table.jsonb('config_schema'); // JSON schema for event configuration
table.timestamp('created_at').defaultTo(knex.fn.now());
});
await knex.schema.createTable('event_instances', (table) => {
table.bigIncrements('id').primary();
table.integer('event_type_id').notNullable().references('id').inTable('event_types');
table.string('name', 200).notNullable();
table.text('description');
table.jsonb('config').notNullable();
table.timestamp('start_time');
table.timestamp('end_time');
table.string('status', 20).notNullable().checkIn(['scheduled', 'active', 'completed', 'cancelled']);
table.integer('created_by'); // Will reference admin_users(id) after table creation
table.timestamp('created_at').defaultTo(knex.fn.now());
table.timestamp('updated_at').defaultTo(knex.fn.now());
table.index(['event_type_id']);
table.index(['status']);
table.index(['start_time']);
});
// Plugin system for extensibility
await knex.schema.createTable('plugins', (table) => {
table.increments('id').primary();
table.string('name', 100).unique().notNullable();
table.string('version', 20).notNullable();
table.text('description');
table.string('plugin_type', 50).notNullable(); // 'combat', 'event', 'resource', etc.
table.boolean('is_active').defaultTo(false);
table.jsonb('config');
table.jsonb('dependencies'); // Array of required plugins
table.jsonb('hooks'); // Available hook points
table.timestamp('created_at').defaultTo(knex.fn.now());
table.timestamp('updated_at').defaultTo(knex.fn.now());
});
// Insert initial system configuration
await knex('system_config').insert([
{
config_key: 'game_tick_interval_ms',
config_value: JSON.stringify(60000),
config_type: 'number',
description: 'Game tick interval in milliseconds',
is_public: false,
},
{
config_key: 'max_user_groups',
config_value: JSON.stringify(10),
config_type: 'number',
description: 'Maximum number of user groups for tick processing',
is_public: false,
},
{
config_key: 'max_retry_attempts',
config_value: JSON.stringify(5),
config_type: 'number',
description: 'Maximum retry attempts for failed ticks',
is_public: false,
},
{
config_key: 'data_retention_days',
config_value: JSON.stringify(30),
config_type: 'number',
description: 'Default data retention period in days',
is_public: false,
},
{
config_key: 'max_colonies_per_player',
config_value: JSON.stringify(10),
config_type: 'number',
description: 'Maximum colonies a player can own',
is_public: true,
},
{
config_key: 'starting_resources',
config_value: JSON.stringify({ scrap: 1000, energy: 500, data_cores: 0, rare_elements: 0 }),
config_type: 'json',
description: 'Starting resources for new players',
is_public: false,
},
{
config_key: 'websocket_ping_interval',
config_value: JSON.stringify(30000),
config_type: 'number',
description: 'WebSocket ping interval in milliseconds',
is_public: false,
},
]);
// Insert initial game tick configuration
await knex('game_tick_config').insert({
tick_interval_ms: 60000,
user_groups_count: 10,
max_retry_attempts: 5,
bonus_tick_threshold: 3,
});
// Insert initial event types
await knex('event_types').insert([
{
name: 'galaxy_crisis',
description: 'Major galaxy-wide crisis events',
trigger_type: 'admin',
config_schema: JSON.stringify({ duration_hours: { type: 'number', min: 1, max: 168 } }),
},
{
name: 'discovery_event',
description: 'Random discovery events triggered by exploration',
trigger_type: 'player',
config_schema: JSON.stringify({ discovery_type: { type: 'string', enum: ['artifact', 'technology', 'resource'] } }),
},
{
name: 'faction_war',
description: 'Large-scale conflicts between factions',
trigger_type: 'mixed',
config_schema: JSON.stringify({ participating_factions: { type: 'array', items: { type: 'number' } } }),
},
]);
// Insert initial plugin for basic combat
await knex('plugins').insert({
name: 'basic_combat',
version: '1.0.0',
description: 'Basic instant combat resolution system',
plugin_type: 'combat',
is_active: true,
config: JSON.stringify({ damage_variance: 0.1, experience_gain: 1.0 }),
hooks: JSON.stringify(['pre_combat', 'post_combat', 'damage_calculation']),
});
};
exports.down = async function (knex) {
await knex.schema.dropTableIfExists('plugins');
await knex.schema.dropTableIfExists('event_instances');
await knex.schema.dropTableIfExists('event_types');
await knex.schema.dropTableIfExists('game_tick_log');
await knex.schema.dropTableIfExists('game_tick_config');
await knex.schema.dropTableIfExists('system_config');
};