Initial commit: Shattered Void MMO foundation
- Complete PostgreSQL database schema with 21+ tables - Express.js server with dual authentication (player/admin) - WebSocket support for real-time features - Comprehensive middleware (auth, validation, logging, security) - Game systems: colonies, resources, fleets, research, factions - Plugin-based combat architecture - Admin panel foundation - Production-ready logging and error handling - Docker support and CI/CD ready - Complete project structure following CLAUDE.md patterns 🤖 Generated with Claude Code (https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
commit
1a60cf55a3
69 changed files with 24471 additions and 0 deletions
637
database-schema.sql
Normal file
637
database-schema.sql
Normal file
|
|
@ -0,0 +1,637 @@
|
|||
-- Shattered Void MMO - Comprehensive Database Schema
|
||||
-- This schema supports all game systems with flexibility for future expansion
|
||||
|
||||
-- ===== CORE SYSTEM TABLES =====
|
||||
|
||||
-- System configuration with hot-reloading support
|
||||
CREATE TABLE system_config (
|
||||
id SERIAL PRIMARY KEY,
|
||||
config_key VARCHAR(100) UNIQUE NOT NULL,
|
||||
config_value JSONB NOT NULL,
|
||||
config_type VARCHAR(20) NOT NULL CHECK (config_type IN ('string', 'number', 'boolean', 'json', 'array')),
|
||||
description TEXT,
|
||||
requires_restart BOOLEAN DEFAULT false,
|
||||
is_public BOOLEAN DEFAULT false, -- Can be exposed to client
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_by INTEGER -- Will reference admin_users(id) after table creation
|
||||
);
|
||||
|
||||
-- Game tick system with user grouping
|
||||
CREATE TABLE game_tick_config (
|
||||
id SERIAL PRIMARY KEY,
|
||||
tick_interval_ms INTEGER NOT NULL DEFAULT 60000,
|
||||
user_groups_count INTEGER NOT NULL DEFAULT 10,
|
||||
max_retry_attempts INTEGER NOT NULL DEFAULT 5,
|
||||
bonus_tick_threshold INTEGER NOT NULL DEFAULT 3,
|
||||
is_active BOOLEAN DEFAULT true,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE game_tick_log (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
tick_number BIGINT NOT NULL,
|
||||
user_group INTEGER NOT NULL,
|
||||
started_at TIMESTAMP NOT NULL,
|
||||
completed_at TIMESTAMP,
|
||||
status VARCHAR(20) NOT NULL CHECK (status IN ('running', 'completed', 'failed', 'retrying')),
|
||||
retry_count INTEGER DEFAULT 0,
|
||||
error_message TEXT,
|
||||
processed_players INTEGER DEFAULT 0,
|
||||
performance_metrics JSONB,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Event system configuration
|
||||
CREATE TABLE event_types (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(100) UNIQUE NOT NULL,
|
||||
description TEXT,
|
||||
trigger_type VARCHAR(20) NOT NULL CHECK (trigger_type IN ('admin', 'player', 'system', 'mixed')),
|
||||
is_active BOOLEAN DEFAULT true,
|
||||
config_schema JSONB, -- JSON schema for event configuration
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE event_instances (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
event_type_id INTEGER NOT NULL REFERENCES event_types(id),
|
||||
name VARCHAR(200) NOT NULL,
|
||||
description TEXT,
|
||||
config JSONB NOT NULL,
|
||||
start_time TIMESTAMP,
|
||||
end_time TIMESTAMP,
|
||||
status VARCHAR(20) NOT NULL CHECK (status IN ('scheduled', 'active', 'completed', 'cancelled')),
|
||||
created_by INTEGER, -- Will reference admin_users(id) after table creation
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Plugin system for extensibility
|
||||
CREATE TABLE plugins (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(100) UNIQUE NOT NULL,
|
||||
version VARCHAR(20) NOT NULL,
|
||||
description TEXT,
|
||||
plugin_type VARCHAR(50) NOT NULL, -- 'combat', 'event', 'resource', etc.
|
||||
is_active BOOLEAN DEFAULT false,
|
||||
config JSONB,
|
||||
dependencies JSONB, -- Array of required plugins
|
||||
hooks JSONB, -- Available hook points
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- ===== USER MANAGEMENT =====
|
||||
|
||||
-- Admin users with role-based access
|
||||
CREATE TABLE admin_users (
|
||||
id SERIAL PRIMARY KEY,
|
||||
username VARCHAR(50) UNIQUE NOT NULL,
|
||||
email VARCHAR(255) UNIQUE NOT NULL,
|
||||
password_hash VARCHAR(255) NOT NULL,
|
||||
role VARCHAR(50) NOT NULL DEFAULT 'moderator',
|
||||
permissions JSONB, -- Specific permissions array
|
||||
is_active BOOLEAN DEFAULT true,
|
||||
last_login TIMESTAMP,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Player accounts
|
||||
CREATE TABLE players (
|
||||
id SERIAL PRIMARY KEY,
|
||||
username VARCHAR(50) UNIQUE NOT NULL,
|
||||
email VARCHAR(255) UNIQUE NOT NULL,
|
||||
password_hash VARCHAR(255) NOT NULL,
|
||||
email_verified BOOLEAN DEFAULT false,
|
||||
email_verification_token VARCHAR(255),
|
||||
reset_password_token VARCHAR(255),
|
||||
reset_password_expires TIMESTAMP,
|
||||
user_group INTEGER NOT NULL CHECK (user_group >= 0 AND user_group < 10),
|
||||
is_active BOOLEAN DEFAULT true,
|
||||
is_banned BOOLEAN DEFAULT false,
|
||||
ban_reason TEXT,
|
||||
ban_expires TIMESTAMP,
|
||||
last_login TIMESTAMP,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Player preferences and game settings
|
||||
CREATE TABLE player_settings (
|
||||
id SERIAL PRIMARY KEY,
|
||||
player_id INTEGER NOT NULL REFERENCES players(id) ON DELETE CASCADE,
|
||||
setting_key VARCHAR(100) NOT NULL,
|
||||
setting_value JSONB NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE(player_id, setting_key)
|
||||
);
|
||||
|
||||
-- WebSocket subscriptions for real-time updates
|
||||
CREATE TABLE player_subscriptions (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
player_id INTEGER NOT NULL REFERENCES players(id) ON DELETE CASCADE,
|
||||
subscription_type VARCHAR(50) NOT NULL, -- 'colony', 'fleet', 'battle', 'event', etc.
|
||||
resource_id INTEGER, -- Specific resource ID (colony_id, fleet_id, etc.)
|
||||
filters JSONB, -- Additional filtering criteria
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
expires_at TIMESTAMP
|
||||
);
|
||||
|
||||
-- ===== GALAXY & COLONIES =====
|
||||
|
||||
-- Planet types with generation rules
|
||||
CREATE TABLE planet_types (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(50) UNIQUE NOT NULL,
|
||||
description TEXT,
|
||||
base_resources JSONB NOT NULL, -- Starting resource deposits
|
||||
resource_modifiers JSONB, -- Production modifiers by resource type
|
||||
max_population INTEGER,
|
||||
special_features JSONB, -- Array of special features
|
||||
rarity_weight INTEGER DEFAULT 100, -- For random generation
|
||||
is_active BOOLEAN DEFAULT true
|
||||
);
|
||||
|
||||
-- Galaxy sectors for organization
|
||||
CREATE TABLE galaxy_sectors (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(50) NOT NULL,
|
||||
coordinates VARCHAR(10) UNIQUE NOT NULL, -- e.g., "A3"
|
||||
description TEXT,
|
||||
danger_level INTEGER DEFAULT 1 CHECK (danger_level BETWEEN 1 AND 10),
|
||||
special_rules JSONB,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Player colonies
|
||||
CREATE TABLE colonies (
|
||||
id SERIAL PRIMARY KEY,
|
||||
player_id INTEGER NOT NULL REFERENCES players(id) ON DELETE CASCADE,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
coordinates VARCHAR(20) UNIQUE NOT NULL, -- Format: "A3-91-X"
|
||||
sector_id INTEGER REFERENCES galaxy_sectors(id),
|
||||
planet_type_id INTEGER NOT NULL REFERENCES planet_types(id),
|
||||
population INTEGER DEFAULT 0 CHECK (population >= 0),
|
||||
max_population INTEGER DEFAULT 1000,
|
||||
morale INTEGER DEFAULT 100 CHECK (morale BETWEEN 0 AND 100),
|
||||
loyalty INTEGER DEFAULT 100 CHECK (loyalty BETWEEN 0 AND 100),
|
||||
founded_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Building types with upgrade paths
|
||||
CREATE TABLE building_types (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(100) UNIQUE NOT NULL,
|
||||
description TEXT,
|
||||
category VARCHAR(50) NOT NULL, -- 'production', 'military', 'research', 'infrastructure'
|
||||
max_level INTEGER DEFAULT 10,
|
||||
base_cost JSONB NOT NULL, -- Resource costs for level 1
|
||||
cost_multiplier DECIMAL(3,2) DEFAULT 1.5, -- Cost increase per level
|
||||
base_production JSONB, -- Resource production at level 1
|
||||
production_multiplier DECIMAL(3,2) DEFAULT 1.2, -- Production increase per level
|
||||
prerequisites JSONB, -- Required buildings/research
|
||||
special_effects JSONB, -- Special abilities or bonuses
|
||||
is_unique BOOLEAN DEFAULT false, -- Only one per colony
|
||||
is_active BOOLEAN DEFAULT true
|
||||
);
|
||||
|
||||
-- Colony buildings
|
||||
CREATE TABLE colony_buildings (
|
||||
id SERIAL PRIMARY KEY,
|
||||
colony_id INTEGER NOT NULL REFERENCES colonies(id) ON DELETE CASCADE,
|
||||
building_type_id INTEGER NOT NULL REFERENCES building_types(id),
|
||||
level INTEGER DEFAULT 1 CHECK (level > 0),
|
||||
health_percentage INTEGER DEFAULT 100 CHECK (health_percentage BETWEEN 0 AND 100),
|
||||
is_under_construction BOOLEAN DEFAULT false,
|
||||
construction_started TIMESTAMP,
|
||||
construction_completes TIMESTAMP,
|
||||
last_production TIMESTAMP,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE(colony_id, building_type_id)
|
||||
);
|
||||
|
||||
-- ===== RESOURCES & ECONOMY =====
|
||||
|
||||
-- Resource types
|
||||
CREATE TABLE resource_types (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(50) UNIQUE NOT NULL,
|
||||
description TEXT,
|
||||
category VARCHAR(30) NOT NULL, -- 'basic', 'advanced', 'rare', 'currency'
|
||||
max_storage INTEGER, -- NULL for unlimited
|
||||
decay_rate DECIMAL(5,4), -- Daily decay percentage
|
||||
trade_value DECIMAL(10,2), -- Base trade value
|
||||
is_tradeable BOOLEAN DEFAULT true,
|
||||
is_active BOOLEAN DEFAULT true
|
||||
);
|
||||
|
||||
-- Player resource stockpiles
|
||||
CREATE TABLE player_resources (
|
||||
id SERIAL PRIMARY KEY,
|
||||
player_id INTEGER NOT NULL REFERENCES players(id) ON DELETE CASCADE,
|
||||
resource_type_id INTEGER NOT NULL REFERENCES resource_types(id),
|
||||
amount BIGINT DEFAULT 0 CHECK (amount >= 0),
|
||||
storage_capacity BIGINT,
|
||||
last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE(player_id, resource_type_id)
|
||||
);
|
||||
|
||||
-- Colony resource production/consumption tracking
|
||||
CREATE TABLE colony_resource_production (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
colony_id INTEGER NOT NULL REFERENCES colonies(id) ON DELETE CASCADE,
|
||||
resource_type_id INTEGER NOT NULL REFERENCES resource_types(id),
|
||||
production_rate INTEGER DEFAULT 0, -- Per hour
|
||||
consumption_rate INTEGER DEFAULT 0, -- Per hour
|
||||
current_stored BIGINT DEFAULT 0,
|
||||
storage_capacity BIGINT,
|
||||
last_calculated TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE(colony_id, resource_type_id)
|
||||
);
|
||||
|
||||
-- Trade system
|
||||
CREATE TABLE trade_routes (
|
||||
id SERIAL PRIMARY KEY,
|
||||
from_colony_id INTEGER NOT NULL REFERENCES colonies(id) ON DELETE CASCADE,
|
||||
to_colony_id INTEGER NOT NULL REFERENCES colonies(id) ON DELETE CASCADE,
|
||||
resource_type_id INTEGER NOT NULL REFERENCES resource_types(id),
|
||||
amount_per_trip INTEGER NOT NULL,
|
||||
price_per_unit DECIMAL(10,2) NOT NULL,
|
||||
status VARCHAR(20) DEFAULT 'active' CHECK (status IN ('active', 'paused', 'cancelled')),
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
CONSTRAINT check_different_colonies CHECK (from_colony_id != to_colony_id)
|
||||
);
|
||||
|
||||
-- ===== FLEET & COMBAT =====
|
||||
|
||||
-- Ship design system
|
||||
CREATE TABLE ship_designs (
|
||||
id SERIAL PRIMARY KEY,
|
||||
player_id INTEGER REFERENCES players(id) ON DELETE CASCADE, -- NULL for standard designs
|
||||
name VARCHAR(100) NOT NULL,
|
||||
ship_class VARCHAR(50) NOT NULL, -- 'fighter', 'corvette', 'destroyer', 'cruiser', 'battleship'
|
||||
hull_type VARCHAR(50) NOT NULL,
|
||||
components JSONB NOT NULL, -- Weapon, shield, engine configurations
|
||||
stats JSONB NOT NULL, -- Calculated stats: hp, attack, defense, speed, etc.
|
||||
cost JSONB NOT NULL, -- Resource cost to build
|
||||
build_time INTEGER NOT NULL, -- In minutes
|
||||
is_public BOOLEAN DEFAULT false, -- Available to all players
|
||||
is_active BOOLEAN DEFAULT true,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Player fleets
|
||||
CREATE TABLE fleets (
|
||||
id SERIAL PRIMARY KEY,
|
||||
player_id INTEGER NOT NULL REFERENCES players(id) ON DELETE CASCADE,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
current_location VARCHAR(20) NOT NULL, -- Coordinates
|
||||
destination VARCHAR(20), -- If moving
|
||||
fleet_status VARCHAR(20) DEFAULT 'idle' CHECK (fleet_status IN ('idle', 'moving', 'in_combat', 'constructing', 'repairing')),
|
||||
movement_started TIMESTAMP,
|
||||
arrival_time TIMESTAMP,
|
||||
last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Ships in fleets
|
||||
CREATE TABLE fleet_ships (
|
||||
id SERIAL PRIMARY KEY,
|
||||
fleet_id INTEGER NOT NULL REFERENCES fleets(id) ON DELETE CASCADE,
|
||||
ship_design_id INTEGER NOT NULL REFERENCES ship_designs(id),
|
||||
quantity INTEGER NOT NULL CHECK (quantity > 0),
|
||||
health_percentage INTEGER DEFAULT 100 CHECK (health_percentage BETWEEN 0 AND 100),
|
||||
experience INTEGER DEFAULT 0,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Combat system with plugin support
|
||||
CREATE TABLE combat_types (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(100) UNIQUE NOT NULL,
|
||||
description TEXT,
|
||||
plugin_name VARCHAR(100), -- References plugins table
|
||||
config JSONB,
|
||||
is_active BOOLEAN DEFAULT true
|
||||
);
|
||||
|
||||
CREATE TABLE battles (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
battle_type VARCHAR(50) NOT NULL,
|
||||
location VARCHAR(20) NOT NULL,
|
||||
combat_type_id INTEGER REFERENCES combat_types(id),
|
||||
participants JSONB NOT NULL, -- Array of fleet/player IDs
|
||||
status VARCHAR(20) DEFAULT 'preparing' CHECK (status IN ('preparing', 'active', 'completed', 'cancelled')),
|
||||
battle_data JSONB, -- Combat calculations and state
|
||||
result JSONB, -- Winner, casualties, loot, etc.
|
||||
started_at TIMESTAMP,
|
||||
completed_at TIMESTAMP,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- ===== RESEARCH & TECHNOLOGY =====
|
||||
|
||||
-- Technology tree
|
||||
CREATE TABLE technologies (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(100) UNIQUE NOT NULL,
|
||||
description TEXT,
|
||||
category VARCHAR(50) NOT NULL, -- 'military', 'industrial', 'social', 'exploration'
|
||||
tier INTEGER NOT NULL DEFAULT 1 CHECK (tier > 0),
|
||||
prerequisites JSONB, -- Array of required technology IDs
|
||||
research_cost JSONB NOT NULL, -- Resource costs
|
||||
research_time INTEGER NOT NULL, -- In minutes
|
||||
effects JSONB, -- Bonuses, unlocks, etc.
|
||||
is_active BOOLEAN DEFAULT true,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Player research progress
|
||||
CREATE TABLE player_research (
|
||||
id SERIAL PRIMARY KEY,
|
||||
player_id INTEGER NOT NULL REFERENCES players(id) ON DELETE CASCADE,
|
||||
technology_id INTEGER NOT NULL REFERENCES technologies(id),
|
||||
status VARCHAR(20) DEFAULT 'available' CHECK (status IN ('unavailable', 'available', 'researching', 'completed')),
|
||||
progress INTEGER DEFAULT 0 CHECK (progress >= 0),
|
||||
started_at TIMESTAMP,
|
||||
completed_at TIMESTAMP,
|
||||
UNIQUE(player_id, technology_id)
|
||||
);
|
||||
|
||||
-- Research labs and facilities
|
||||
CREATE TABLE research_facilities (
|
||||
id SERIAL PRIMARY KEY,
|
||||
colony_id INTEGER NOT NULL REFERENCES colonies(id) ON DELETE CASCADE,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
facility_type VARCHAR(50) NOT NULL,
|
||||
research_bonus DECIMAL(3,2) DEFAULT 1.0, -- Multiplier for research speed
|
||||
specialization JSONB, -- Categories this facility is good at
|
||||
is_active BOOLEAN DEFAULT true,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- ===== FACTIONS & DIPLOMACY =====
|
||||
|
||||
-- Player factions/alliances
|
||||
CREATE TABLE factions (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(100) UNIQUE NOT NULL,
|
||||
description TEXT,
|
||||
tag VARCHAR(10) UNIQUE NOT NULL, -- Short identifier
|
||||
leader_id INTEGER REFERENCES players(id),
|
||||
faction_type VARCHAR(20) DEFAULT 'alliance' CHECK (faction_type IN ('alliance', 'corporation', 'empire')),
|
||||
is_recruiting BOOLEAN DEFAULT true,
|
||||
requirements JSONB, -- Join requirements
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Faction membership
|
||||
CREATE TABLE faction_members (
|
||||
id SERIAL PRIMARY KEY,
|
||||
faction_id INTEGER NOT NULL REFERENCES factions(id) ON DELETE CASCADE,
|
||||
player_id INTEGER NOT NULL REFERENCES players(id) ON DELETE CASCADE,
|
||||
rank VARCHAR(50) DEFAULT 'member',
|
||||
permissions JSONB, -- What they can do
|
||||
joined_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
contribution_score INTEGER DEFAULT 0,
|
||||
UNIQUE(faction_id, player_id)
|
||||
);
|
||||
|
||||
-- Diplomatic relations
|
||||
CREATE TABLE diplomatic_relations (
|
||||
id SERIAL PRIMARY KEY,
|
||||
faction_a_id INTEGER NOT NULL REFERENCES factions(id) ON DELETE CASCADE,
|
||||
faction_b_id INTEGER NOT NULL REFERENCES factions(id) ON DELETE CASCADE,
|
||||
relation_type VARCHAR(20) NOT NULL CHECK (relation_type IN ('allied', 'friendly', 'neutral', 'hostile', 'war')),
|
||||
established_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
established_by INTEGER REFERENCES players(id),
|
||||
CONSTRAINT check_different_factions CHECK (faction_a_id != faction_b_id),
|
||||
UNIQUE(faction_a_id, faction_b_id)
|
||||
);
|
||||
|
||||
-- ===== AUDIT & STATISTICS =====
|
||||
|
||||
-- Comprehensive audit log
|
||||
CREATE TABLE audit_log (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
entity_type VARCHAR(50) NOT NULL, -- 'player', 'colony', 'fleet', 'battle', etc.
|
||||
entity_id INTEGER NOT NULL,
|
||||
action VARCHAR(100) NOT NULL,
|
||||
actor_type VARCHAR(20) NOT NULL CHECK (actor_type IN ('player', 'admin', 'system')),
|
||||
actor_id INTEGER,
|
||||
changes JSONB, -- Before/after values
|
||||
metadata JSONB, -- Additional context
|
||||
ip_address INET,
|
||||
user_agent TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Data retention policy
|
||||
CREATE TABLE data_retention_policies (
|
||||
id SERIAL PRIMARY KEY,
|
||||
table_name VARCHAR(100) NOT NULL,
|
||||
retention_days INTEGER NOT NULL DEFAULT 30,
|
||||
archive_before_delete BOOLEAN DEFAULT true,
|
||||
is_active BOOLEAN DEFAULT true,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE(table_name)
|
||||
);
|
||||
|
||||
-- Game statistics for analysis
|
||||
CREATE TABLE game_statistics (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
stat_type VARCHAR(100) NOT NULL,
|
||||
stat_key VARCHAR(200) NOT NULL,
|
||||
stat_value DECIMAL(15,4) NOT NULL,
|
||||
dimensions JSONB, -- Additional grouping dimensions
|
||||
recorded_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Performance metrics
|
||||
CREATE TABLE performance_metrics (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
metric_name VARCHAR(100) NOT NULL,
|
||||
metric_value DECIMAL(10,4) NOT NULL,
|
||||
tags JSONB, -- Additional metadata
|
||||
recorded_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- ===== INDEXES FOR PERFORMANCE =====
|
||||
|
||||
-- User management indexes
|
||||
CREATE INDEX idx_players_user_group ON players(user_group);
|
||||
CREATE INDEX idx_players_email ON players(email);
|
||||
CREATE INDEX idx_players_username ON players(username);
|
||||
CREATE INDEX idx_player_subscriptions_player_id ON player_subscriptions(player_id);
|
||||
CREATE INDEX idx_player_subscriptions_type ON player_subscriptions(subscription_type);
|
||||
CREATE INDEX idx_player_subscriptions_expires ON player_subscriptions(expires_at);
|
||||
|
||||
-- Colony and building indexes
|
||||
CREATE INDEX idx_colonies_player_id ON colonies(player_id);
|
||||
CREATE INDEX idx_colonies_coordinates ON colonies(coordinates);
|
||||
CREATE INDEX idx_colonies_sector ON colonies(sector_id);
|
||||
CREATE INDEX idx_colony_buildings_colony_id ON colony_buildings(colony_id);
|
||||
CREATE INDEX idx_colony_buildings_construction ON colony_buildings(construction_completes) WHERE is_under_construction = true;
|
||||
|
||||
-- Resource indexes
|
||||
CREATE INDEX idx_player_resources_player_id ON player_resources(player_id);
|
||||
CREATE INDEX idx_colony_production_colony_id ON colony_resource_production(colony_id);
|
||||
CREATE INDEX idx_trade_routes_from_colony ON trade_routes(from_colony_id);
|
||||
CREATE INDEX idx_trade_routes_to_colony ON trade_routes(to_colony_id);
|
||||
|
||||
-- Fleet and combat indexes
|
||||
CREATE INDEX idx_ship_designs_player_id ON ship_designs(player_id);
|
||||
CREATE INDEX idx_ship_designs_class ON ship_designs(ship_class);
|
||||
CREATE INDEX idx_fleets_player_id ON fleets(player_id);
|
||||
CREATE INDEX idx_fleets_location ON fleets(current_location);
|
||||
CREATE INDEX idx_fleets_arrival ON fleets(arrival_time) WHERE arrival_time IS NOT NULL;
|
||||
CREATE INDEX idx_fleet_ships_fleet_id ON fleet_ships(fleet_id);
|
||||
CREATE INDEX idx_battles_location ON battles(location);
|
||||
CREATE INDEX idx_battles_status ON battles(status);
|
||||
CREATE INDEX idx_battles_completed ON battles(completed_at);
|
||||
|
||||
-- Research indexes
|
||||
CREATE INDEX idx_player_research_player_id ON player_research(player_id);
|
||||
CREATE INDEX idx_player_research_status ON player_research(status);
|
||||
CREATE INDEX idx_research_facilities_colony_id ON research_facilities(colony_id);
|
||||
|
||||
-- Faction indexes
|
||||
CREATE INDEX idx_factions_leader_id ON factions(leader_id);
|
||||
CREATE INDEX idx_faction_members_faction_id ON faction_members(faction_id);
|
||||
CREATE INDEX idx_faction_members_player_id ON faction_members(player_id);
|
||||
CREATE INDEX idx_diplomatic_relations_faction_a ON diplomatic_relations(faction_a_id);
|
||||
CREATE INDEX idx_diplomatic_relations_faction_b ON diplomatic_relations(faction_b_id);
|
||||
|
||||
-- Audit and statistics indexes
|
||||
CREATE INDEX idx_audit_log_entity ON audit_log(entity_type, entity_id);
|
||||
CREATE INDEX idx_audit_log_actor ON audit_log(actor_type, actor_id);
|
||||
CREATE INDEX idx_audit_log_created_at ON audit_log(created_at);
|
||||
CREATE INDEX idx_audit_log_action ON audit_log(action);
|
||||
CREATE INDEX idx_game_statistics_type_key ON game_statistics(stat_type, stat_key);
|
||||
CREATE INDEX idx_game_statistics_recorded_at ON game_statistics(recorded_at);
|
||||
CREATE INDEX idx_performance_metrics_name ON performance_metrics(metric_name);
|
||||
CREATE INDEX idx_performance_metrics_recorded_at ON performance_metrics(recorded_at);
|
||||
|
||||
-- Game tick indexes
|
||||
CREATE INDEX idx_game_tick_log_tick_number ON game_tick_log(tick_number);
|
||||
CREATE INDEX idx_game_tick_log_user_group ON game_tick_log(user_group);
|
||||
CREATE INDEX idx_game_tick_log_status ON game_tick_log(status);
|
||||
|
||||
-- Event system indexes
|
||||
CREATE INDEX idx_event_instances_event_type ON event_instances(event_type_id);
|
||||
CREATE INDEX idx_event_instances_status ON event_instances(status);
|
||||
CREATE INDEX idx_event_instances_start_time ON event_instances(start_time);
|
||||
|
||||
-- ===== ADD FOREIGN KEY CONSTRAINTS =====
|
||||
|
||||
-- Add foreign key constraints that couldn't be added during table creation
|
||||
ALTER TABLE system_config ADD CONSTRAINT fk_system_config_admin FOREIGN KEY (updated_by) REFERENCES admin_users(id);
|
||||
ALTER TABLE event_instances ADD CONSTRAINT fk_event_instances_admin FOREIGN KEY (created_by) REFERENCES admin_users(id);
|
||||
|
||||
-- ===== TRIGGERS FOR AUTOMATIC TIMESTAMPS =====
|
||||
|
||||
-- Function to automatically update updated_at timestamps
|
||||
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = CURRENT_TIMESTAMP;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ language 'plpgsql';
|
||||
|
||||
-- Apply updated_at triggers to relevant tables
|
||||
CREATE TRIGGER update_system_config_updated_at BEFORE UPDATE ON system_config FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
CREATE TRIGGER update_game_tick_config_updated_at BEFORE UPDATE ON game_tick_config FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
CREATE TRIGGER update_event_instances_updated_at BEFORE UPDATE ON event_instances FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
CREATE TRIGGER update_plugins_updated_at BEFORE UPDATE ON plugins FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
CREATE TRIGGER update_admin_users_updated_at BEFORE UPDATE ON admin_users FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
CREATE TRIGGER update_players_updated_at BEFORE UPDATE ON players FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
CREATE TRIGGER update_player_settings_updated_at BEFORE UPDATE ON player_settings FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
CREATE TRIGGER update_colonies_updated_at BEFORE UPDATE ON colonies FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
CREATE TRIGGER update_colony_buildings_updated_at BEFORE UPDATE ON colony_buildings FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
CREATE TRIGGER update_ship_designs_updated_at BEFORE UPDATE ON ship_designs FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
-- ===== INITIAL DATA =====
|
||||
|
||||
-- Insert initial system configuration
|
||||
INSERT INTO system_config (config_key, config_value, config_type, description, is_public) VALUES
|
||||
('game_tick_interval_ms', '60000', 'number', 'Game tick interval in milliseconds', false),
|
||||
('max_user_groups', '10', 'number', 'Maximum number of user groups for tick processing', false),
|
||||
('max_retry_attempts', '5', 'number', 'Maximum retry attempts for failed ticks', false),
|
||||
('data_retention_days', '30', 'number', 'Default data retention period in days', false),
|
||||
('max_colonies_per_player', '10', 'number', 'Maximum colonies a player can own', true),
|
||||
('starting_resources', '{"scrap": 1000, "energy": 500, "data_cores": 0, "rare_elements": 0}', 'json', 'Starting resources for new players', false),
|
||||
('websocket_ping_interval', '30000', 'number', 'WebSocket ping interval in milliseconds', false);
|
||||
|
||||
-- Insert resource types
|
||||
INSERT INTO resource_types (name, description, category, is_tradeable) VALUES
|
||||
('scrap', 'Basic salvaged materials from the ruins of civilization', 'basic', true),
|
||||
('energy', 'Power cells and energy storage units', 'basic', true),
|
||||
('data_cores', 'Advanced information storage containing pre-collapse knowledge', 'advanced', true),
|
||||
('rare_elements', 'Exotic materials required for advanced technologies', 'rare', true);
|
||||
|
||||
-- Insert initial planet types
|
||||
INSERT INTO planet_types (name, description, base_resources, resource_modifiers, max_population, rarity_weight) VALUES
|
||||
('Terran', 'Earth-like worlds with balanced resources', '{"scrap": 500, "energy": 300}', '{"scrap": 1.0, "energy": 1.0, "data_cores": 1.0, "rare_elements": 1.0}', 10000, 100),
|
||||
('Industrial', 'Former manufacturing worlds rich in salvageable materials', '{"scrap": 1000, "energy": 200}', '{"scrap": 1.5, "energy": 0.8, "data_cores": 1.2, "rare_elements": 0.9}', 8000, 80),
|
||||
('Research', 'Academic worlds with data archives and laboratories', '{"scrap": 300, "energy": 400, "data_cores": 100}', '{"scrap": 0.7, "energy": 1.1, "data_cores": 2.0, "rare_elements": 1.3}', 6000, 60),
|
||||
('Mining', 'Resource extraction worlds with rare element deposits', '{"scrap": 400, "energy": 250, "rare_elements": 20}', '{"scrap": 1.1, "energy": 0.9, "data_cores": 0.8, "rare_elements": 2.5}', 7000, 70),
|
||||
('Fortress', 'Heavily fortified military installations', '{"scrap": 600, "energy": 500}', '{"scrap": 1.2, "energy": 1.3, "data_cores": 1.1, "rare_elements": 1.1}', 5000, 40),
|
||||
('Derelict', 'Abandoned worlds with scattered ruins and mysteries', '{"scrap": 200, "energy": 100, "data_cores": 50, "rare_elements": 10}', '{"scrap": 0.8, "energy": 0.6, "data_cores": 1.5, "rare_elements": 1.8}', 3000, 30);
|
||||
|
||||
-- Insert initial building types
|
||||
INSERT INTO building_types (name, description, category, max_level, base_cost, base_production, special_effects) VALUES
|
||||
('Command Center', 'Central administration building that coordinates colony operations', 'infrastructure', 10, '{"scrap": 100, "energy": 50}', '{}', '{"colony_slots": 1}'),
|
||||
('Salvage Yard', 'Processes scrap metal and salvageable materials', 'production', 10, '{"scrap": 50, "energy": 25}', '{"scrap": 10}', '{}'),
|
||||
('Power Plant', 'Generates energy for colony operations', 'production', 10, '{"scrap": 75, "energy": 0}', '{"energy": 8}', '{}'),
|
||||
('Research Lab', 'Conducts technological research and development', 'research', 10, '{"scrap": 100, "energy": 75, "data_cores": 10}', '{}', '{"research_speed": 0.1}'),
|
||||
('Housing Complex', 'Provides living space for colony population', 'infrastructure', 15, '{"scrap": 60, "energy": 30}', '{}', '{"population_capacity": 100}'),
|
||||
('Defense Grid', 'Automated defense systems protecting the colony', 'military', 10, '{"scrap": 150, "energy": 100, "rare_elements": 5}', '{}', '{"defense_rating": 50}'),
|
||||
('Data Archive', 'Stores and processes information from data cores', 'research', 8, '{"scrap": 80, "energy": 60, "data_cores": 5}', '{"data_cores": 2}', '{"research_bonus": 0.05}'),
|
||||
('Mining Facility', 'Extracts rare elements from planetary deposits', 'production', 12, '{"scrap": 200, "energy": 150, "data_cores": 20}', '{"rare_elements": 1}', '{}');
|
||||
|
||||
-- Insert initial game tick configuration
|
||||
INSERT INTO game_tick_config (tick_interval_ms, user_groups_count, max_retry_attempts, bonus_tick_threshold) VALUES
|
||||
(60000, 10, 5, 3);
|
||||
|
||||
-- Insert basic combat type
|
||||
INSERT INTO combat_types (name, description, config) VALUES
|
||||
('instant_resolution', 'Basic instant combat resolution with detailed logs', '{"calculate_experience": true, "detailed_logs": true}');
|
||||
|
||||
-- Insert initial event types
|
||||
INSERT INTO event_types (name, description, trigger_type, config_schema) VALUES
|
||||
('galaxy_crisis', 'Major galaxy-wide crisis events', 'admin', '{"duration_hours": {"type": "number", "min": 1, "max": 168}}'),
|
||||
('discovery_event', 'Random discovery events triggered by exploration', 'player', '{"discovery_type": {"type": "string", "enum": ["artifact", "technology", "resource"]}}'),
|
||||
('faction_war', 'Large-scale conflicts between factions', 'mixed', '{"participating_factions": {"type": "array", "items": {"type": "number"}}}');
|
||||
|
||||
-- Insert data retention policies
|
||||
INSERT INTO data_retention_policies (table_name, retention_days, archive_before_delete) VALUES
|
||||
('audit_log', 90, true),
|
||||
('game_tick_log', 7, false),
|
||||
('battles', 30, true),
|
||||
('performance_metrics', 14, false),
|
||||
('game_statistics', 365, true);
|
||||
|
||||
-- Insert initial galaxy sectors
|
||||
INSERT INTO galaxy_sectors (name, coordinates, description, danger_level) VALUES
|
||||
('Core Worlds', 'A1', 'The former heart of galactic civilization', 3),
|
||||
('Industrial Belt', 'B2', 'Manufacturing and resource processing sector', 4),
|
||||
('Frontier Region', 'C3', 'Outer rim territories with unexplored systems', 6),
|
||||
('Research Zone', 'D4', 'Former academic and scientific installations', 2),
|
||||
('Contested Space', 'E5', 'Battlegrounds of the great collapse', 8),
|
||||
('Dead Zone', 'F6', 'Heavily damaged region with dangerous anomalies', 9);
|
||||
|
||||
-- Create initial admin user (password should be changed immediately)
|
||||
INSERT INTO admin_users (username, email, password_hash, role, permissions) VALUES
|
||||
('admin', 'admin@shatteredvoid.game', '$2b$10$example.hash.change.immediately', 'administrator', '["all"]');
|
||||
|
||||
-- Insert initial plugin for basic combat
|
||||
INSERT INTO plugins (name, version, description, plugin_type, is_active, config, hooks) VALUES
|
||||
('basic_combat', '1.0.0', 'Basic instant combat resolution system', 'combat', true, '{"damage_variance": 0.1, "experience_gain": 1.0}', '["pre_combat", "post_combat", "damage_calculation"]');
|
||||
Loading…
Add table
Add a link
Reference in a new issue