971 行
48 KiB
MySQL
971 行
48 KiB
MySQL
|
|
-- TDD-04 数据库表结构初始化
|
|||
|
|
-- 适用 PostgreSQL 16 + pg_partman(分区扩展可选)
|
|||
|
|
-- 命名约定:小写下划线,主键 uuid,金额 numeric(20,4),JSONB 存半结构化数据
|
|||
|
|
|
|||
|
|
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
|||
|
|
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
-- 0. 开发参考表(种族、境界、货币静态配置)
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS race_templates (
|
|||
|
|
id VARCHAR(32) PRIMARY KEY,
|
|||
|
|
name VARCHAR(64) NOT NULL,
|
|||
|
|
category VARCHAR(16) NOT NULL DEFAULT 'common', -- common / rare
|
|||
|
|
can_create BOOLEAN NOT NULL DEFAULT true,
|
|||
|
|
description TEXT,
|
|||
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
-- 1. 账号与角色
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS players (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
nakama_user_id UUID UNIQUE,
|
|||
|
|
platform VARCHAR(32),
|
|||
|
|
device_id_hash VARCHAR(128) UNIQUE,
|
|||
|
|
status VARCHAR(16) NOT NULL DEFAULT 'active', -- active / banned / deleted
|
|||
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|||
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS characters (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
player_id UUID NOT NULL REFERENCES players(id) ON DELETE CASCADE,
|
|||
|
|
name VARCHAR(64) UNIQUE NOT NULL,
|
|||
|
|
race_id VARCHAR(32) NOT NULL,
|
|||
|
|
birth_race_id VARCHAR(32) NOT NULL,
|
|||
|
|
birth_world_tier SMALLINT NOT NULL DEFAULT 1,
|
|||
|
|
world_tier SMALLINT NOT NULL DEFAULT 1,
|
|||
|
|
realm_tier SMALLINT NOT NULL DEFAULT 1,
|
|||
|
|
minor_realm SMALLINT NOT NULL DEFAULT 1,
|
|||
|
|
realm_status VARCHAR(16) NOT NULL DEFAULT 'normal', -- normal / tribulation_pending / breakthrough_ready
|
|||
|
|
level INT NOT NULL DEFAULT 1,
|
|||
|
|
exp BIGINT NOT NULL DEFAULT 0,
|
|||
|
|
power BIGINT NOT NULL DEFAULT 0,
|
|||
|
|
status VARCHAR(16) NOT NULL DEFAULT 'active', -- active / dead / sealed / deleted
|
|||
|
|
base_stats JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
battle_stats JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
san_current SMALLINT NOT NULL DEFAULT 100,
|
|||
|
|
san_max SMALLINT NOT NULL DEFAULT 100,
|
|||
|
|
crime_score INT NOT NULL DEFAULT 0,
|
|||
|
|
heavenly_value INT NOT NULL DEFAULT 0,
|
|||
|
|
karma_value INT NOT NULL DEFAULT 0,
|
|||
|
|
reputation_score INT NOT NULL DEFAULT 0,
|
|||
|
|
mercenary_score INT NOT NULL DEFAULT 0,
|
|||
|
|
hunter_prestige INT NOT NULL DEFAULT 0,
|
|||
|
|
last_online_at TIMESTAMPTZ,
|
|||
|
|
daily_reset_at TIMESTAMPTZ,
|
|||
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|||
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_characters_player ON characters(player_id);
|
|||
|
|
CREATE INDEX idx_characters_realm_rank ON characters(world_tier, realm_tier, power DESC);
|
|||
|
|
CREATE INDEX idx_characters_realm_minor ON characters(realm_tier, minor_realm, power DESC);
|
|||
|
|
CREATE INDEX idx_characters_last_online ON characters(last_online_at);
|
|||
|
|
CREATE INDEX idx_characters_status ON characters(status);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS character_race_states (
|
|||
|
|
character_id UUID PRIMARY KEY REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
main_race_id VARCHAR(32) NOT NULL,
|
|||
|
|
sub_branch_id VARCHAR(32),
|
|||
|
|
bloodline_data JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
is_rare_race BOOLEAN NOT NULL DEFAULT false,
|
|||
|
|
rebirth_count SMALLINT NOT NULL DEFAULT 0,
|
|||
|
|
conversion_cooldown_until TIMESTAMPTZ,
|
|||
|
|
race_talents JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
hidden_talents JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS race_currency_wallets (
|
|||
|
|
character_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
race_currency_code VARCHAR(32) NOT NULL,
|
|||
|
|
amount NUMERIC(20,4) NOT NULL DEFAULT 0,
|
|||
|
|
total_earned NUMERIC(20,4) NOT NULL DEFAULT 0,
|
|||
|
|
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
|||
|
|
PRIMARY KEY (character_id, race_currency_code)
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
-- 2. 境界
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS realms (
|
|||
|
|
tier SMALLINT PRIMARY KEY,
|
|||
|
|
minor_realm_max SMALLINT NOT NULL DEFAULT 3,
|
|||
|
|
name VARCHAR(64) NOT NULL,
|
|||
|
|
world_tier SMALLINT NOT NULL,
|
|||
|
|
main_currency_code VARCHAR(32) NOT NULL,
|
|||
|
|
is_tribulation_required BOOLEAN NOT NULL DEFAULT true,
|
|||
|
|
base_success_rate NUMERIC(5,4) NOT NULL DEFAULT 0.5,
|
|||
|
|
attr_growth_template JSONB NOT NULL DEFAULT '{}'
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS character_realms (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
character_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
realm_tier SMALLINT NOT NULL,
|
|||
|
|
max_minor_reached SMALLINT NOT NULL DEFAULT 1,
|
|||
|
|
exp_in_tier BIGINT NOT NULL DEFAULT 0,
|
|||
|
|
stats_snapshot JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
is_current BOOLEAN NOT NULL DEFAULT false,
|
|||
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_character_realms_character ON character_realms(character_id);
|
|||
|
|
CREATE INDEX idx_character_realms_current ON character_realms(character_id, is_current);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS realm_breakthrough_records (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
character_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
from_realm_tier SMALLINT NOT NULL,
|
|||
|
|
to_realm_tier SMALLINT NOT NULL,
|
|||
|
|
from_minor_realm SMALLINT NOT NULL,
|
|||
|
|
to_minor_realm SMALLINT NOT NULL,
|
|||
|
|
is_success BOOLEAN NOT NULL,
|
|||
|
|
is_break_world_barrier BOOLEAN NOT NULL DEFAULT false,
|
|||
|
|
source_world_tier SMALLINT NOT NULL,
|
|||
|
|
target_world_tier SMALLINT NOT NULL,
|
|||
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_realm_breakthrough_character ON realm_breakthrough_records(character_id);
|
|||
|
|
CREATE INDEX idx_realm_breakthrough_created ON realm_breakthrough_records(created_at);
|
|||
|
|
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
-- 3. 功法与技能
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS manuals (
|
|||
|
|
id VARCHAR(64) PRIMARY KEY,
|
|||
|
|
name VARCHAR(128) NOT NULL,
|
|||
|
|
category VARCHAR(32) NOT NULL, -- universal / profession / racial / unique
|
|||
|
|
domain VARCHAR(32) NOT NULL,
|
|||
|
|
element VARCHAR(16) NOT NULL DEFAULT 'none',
|
|||
|
|
alignment VARCHAR(16) NOT NULL DEFAULT 'neutral',
|
|||
|
|
max_layers SMALLINT NOT NULL DEFAULT 1,
|
|||
|
|
required_race VARCHAR(32)[],
|
|||
|
|
required_profession VARCHAR(32)[],
|
|||
|
|
base_attr JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
skill_unlock_layers JSONB NOT NULL DEFAULT '[]',
|
|||
|
|
version INT NOT NULL DEFAULT 1
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS character_manuals (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
character_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
manual_id VARCHAR(64) NOT NULL REFERENCES manuals(id),
|
|||
|
|
instance_data JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
is_buffing BOOLEAN NOT NULL DEFAULT false,
|
|||
|
|
buff_data JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
source_tag VARCHAR(32) NOT NULL DEFAULT 'ORIGINAL',
|
|||
|
|
can_copy_to_jade_slip BOOLEAN NOT NULL DEFAULT false,
|
|||
|
|
copy_count_left SMALLINT NOT NULL DEFAULT 0,
|
|||
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|||
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_character_manuals_character ON character_manuals(character_id);
|
|||
|
|
CREATE INDEX idx_character_manuals_buffing ON character_manuals(character_id, is_buffing);
|
|||
|
|
CREATE INDEX idx_character_manuals_manual ON character_manuals(manual_id);
|
|||
|
|
CREATE INDEX idx_character_manuals_instance_gin ON character_manuals USING GIN (instance_data jsonb_path_ops);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS skills (
|
|||
|
|
id VARCHAR(64) PRIMARY KEY,
|
|||
|
|
name VARCHAR(128) NOT NULL,
|
|||
|
|
category VARCHAR(32) NOT NULL,
|
|||
|
|
domain VARCHAR(32) NOT NULL,
|
|||
|
|
archetype VARCHAR(32) NOT NULL,
|
|||
|
|
element VARCHAR(16) NOT NULL DEFAULT 'none',
|
|||
|
|
alignment VARCHAR(16) NOT NULL DEFAULT 'neutral',
|
|||
|
|
damage_type VARCHAR(16) NOT NULL DEFAULT 'physical',
|
|||
|
|
scaling_attr VARCHAR(8),
|
|||
|
|
is_eldritch BOOLEAN NOT NULL DEFAULT false,
|
|||
|
|
san_cost SMALLINT NOT NULL DEFAULT 0,
|
|||
|
|
san_gate JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
san_scaling NUMERIC(6,4) NOT NULL DEFAULT 0,
|
|||
|
|
requirements JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
continuous_cost JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
flow VARCHAR(32) NOT NULL DEFAULT 'transcript_jade_ok',
|
|||
|
|
base_template JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
version INT NOT NULL DEFAULT 1
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS character_skills (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
character_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
skill_id VARCHAR(64) NOT NULL REFERENCES skills(id),
|
|||
|
|
custom_name VARCHAR(128),
|
|||
|
|
instance_data JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
source_tag VARCHAR(32) NOT NULL DEFAULT 'ORIGINAL',
|
|||
|
|
proficiency INT NOT NULL DEFAULT 0,
|
|||
|
|
is_unique BOOLEAN NOT NULL DEFAULT false,
|
|||
|
|
unique_holder_until TIMESTAMPTZ,
|
|||
|
|
lineage JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|||
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_character_skills_character ON character_skills(character_id);
|
|||
|
|
CREATE INDEX idx_character_skills_unique ON character_skills(character_id, is_unique);
|
|||
|
|
CREATE INDEX idx_character_skills_skill ON character_skills(skill_id);
|
|||
|
|
CREATE INDEX idx_character_skills_instance_gin ON character_skills USING GIN (instance_data jsonb_path_ops);
|
|||
|
|
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
-- 4. 物品、装备与经济
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS items (
|
|||
|
|
id VARCHAR(64) PRIMARY KEY,
|
|||
|
|
name VARCHAR(128) NOT NULL,
|
|||
|
|
category VARCHAR(32) NOT NULL,
|
|||
|
|
sub_category VARCHAR(32),
|
|||
|
|
stackable BOOLEAN NOT NULL DEFAULT false,
|
|||
|
|
max_stack INT NOT NULL DEFAULT 1,
|
|||
|
|
bind_type VARCHAR(16) NOT NULL DEFAULT 'none',
|
|||
|
|
world_tier SMALLINT NOT NULL DEFAULT 1,
|
|||
|
|
base_attr_template JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
random_affix_pool JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
script_id VARCHAR(64),
|
|||
|
|
version INT NOT NULL DEFAULT 1
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS inventories (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
character_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
item_id VARCHAR(64) NOT NULL REFERENCES items(id),
|
|||
|
|
slot_type VARCHAR(16) NOT NULL DEFAULT 'bag', -- bag / warehouse / mail / auction_escrow
|
|||
|
|
quantity INT NOT NULL DEFAULT 1,
|
|||
|
|
instance_data JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
is_stolen BOOLEAN NOT NULL DEFAULT false,
|
|||
|
|
blood_debt_mark BOOLEAN NOT NULL DEFAULT false,
|
|||
|
|
can_trade BOOLEAN NOT NULL DEFAULT true,
|
|||
|
|
acquired_at TIMESTAMPTZ DEFAULT NOW(),
|
|||
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_inventories_character_slot ON inventories(character_id, slot_type);
|
|||
|
|
CREATE INDEX idx_inventories_item ON inventories(item_id);
|
|||
|
|
CREATE INDEX idx_inventories_instance_gin ON inventories USING GIN (instance_data jsonb_path_ops);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS equipments (
|
|||
|
|
character_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
slot_name VARCHAR(32) NOT NULL, -- weapon / head / body / hand / foot / accessory1 / accessory2 / life_item
|
|||
|
|
inventory_id UUID REFERENCES inventories(id) ON DELETE SET NULL,
|
|||
|
|
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
|||
|
|
PRIMARY KEY (character_id, slot_name)
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_equipments_inventory ON equipments(inventory_id);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS currencies (
|
|||
|
|
code VARCHAR(32) PRIMARY KEY,
|
|||
|
|
name VARCHAR(64) NOT NULL,
|
|||
|
|
world_tier SMALLINT NOT NULL DEFAULT 1,
|
|||
|
|
is_premium BOOLEAN NOT NULL DEFAULT false,
|
|||
|
|
exchange_rules JSONB NOT NULL DEFAULT '{}'
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS currency_balances (
|
|||
|
|
character_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
currency_code VARCHAR(32) NOT NULL REFERENCES currencies(code),
|
|||
|
|
amount NUMERIC(20,4) NOT NULL DEFAULT 0,
|
|||
|
|
total_earned NUMERIC(20,4) NOT NULL DEFAULT 0,
|
|||
|
|
total_spent NUMERIC(20,4) NOT NULL DEFAULT 0,
|
|||
|
|
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
|||
|
|
PRIMARY KEY (character_id, currency_code)
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
-- 经济审计日志(建议按 created_at 月分区,保留 12 个月)
|
|||
|
|
CREATE TABLE IF NOT EXISTS economy_audit_logs (
|
|||
|
|
id BIGSERIAL PRIMARY KEY,
|
|||
|
|
character_id UUID REFERENCES characters(id) ON DELETE SET NULL,
|
|||
|
|
entity_type VARCHAR(16) NOT NULL, -- character / guild / system
|
|||
|
|
entity_id UUID NOT NULL,
|
|||
|
|
currency_code VARCHAR(32) NOT NULL,
|
|||
|
|
flow_type VARCHAR(16) NOT NULL, -- faucet / sink / transfer
|
|||
|
|
reason_code VARCHAR(64) NOT NULL,
|
|||
|
|
amount NUMERIC(20,4) NOT NULL,
|
|||
|
|
balance_after NUMERIC(20,4),
|
|||
|
|
related_id UUID,
|
|||
|
|
world_tier SMALLINT NOT NULL,
|
|||
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_economy_audit_character_reason ON economy_audit_logs(character_id, reason_code, created_at);
|
|||
|
|
CREATE INDEX idx_economy_audit_entity ON economy_audit_logs(entity_id, created_at);
|
|||
|
|
CREATE INDEX idx_economy_audit_currency ON economy_audit_logs(currency_code, created_at);
|
|||
|
|
CREATE INDEX idx_economy_audit_flow ON economy_audit_logs(flow_type, created_at);
|
|||
|
|
CREATE INDEX idx_economy_audit_world_tier ON economy_audit_logs(world_tier, created_at);
|
|||
|
|
CREATE INDEX idx_economy_audit_created ON economy_audit_logs(created_at);
|
|||
|
|
COMMENT ON TABLE economy_audit_logs IS '大表建议:按 created_at 月分区,保留 12 个月(可用 pg_partman)';
|
|||
|
|
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
-- 5. 组织(门派/帮派/家族/自建宗门)
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS guilds (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
name VARCHAR(128) UNIQUE NOT NULL,
|
|||
|
|
org_type VARCHAR(16) NOT NULL, -- system_sect / player_sect / guild / family
|
|||
|
|
world_tier SMALLINT NOT NULL DEFAULT 1,
|
|||
|
|
region_id UUID,
|
|||
|
|
zone_id UUID,
|
|||
|
|
leader_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
level SMALLINT NOT NULL DEFAULT 1,
|
|||
|
|
reputation INT NOT NULL DEFAULT 0,
|
|||
|
|
member_limit INT NOT NULL DEFAULT 50,
|
|||
|
|
tax_rate NUMERIC(5,4) NOT NULL DEFAULT 0.20,
|
|||
|
|
diplomacy_policy JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
building_levels JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
funds JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
status VARCHAR(16) NOT NULL DEFAULT 'active', -- active / dissolved / blacklisted
|
|||
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|||
|
|
dissolved_at TIMESTAMPTZ
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_guilds_type_status ON guilds(org_type, status);
|
|||
|
|
CREATE INDEX idx_guilds_world_tier ON guilds(world_tier, status);
|
|||
|
|
CREATE INDEX idx_guilds_leader ON guilds(leader_id);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS guild_members (
|
|||
|
|
guild_id UUID NOT NULL REFERENCES guilds(id) ON DELETE CASCADE,
|
|||
|
|
character_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
role VARCHAR(32) NOT NULL DEFAULT 'member', -- leader / vice / elder / elder_council / member / disciple_manager
|
|||
|
|
joined_at TIMESTAMPTZ DEFAULT NOW(),
|
|||
|
|
contribution JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
daily_quota JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
|||
|
|
PRIMARY KEY (guild_id, character_id)
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_guild_members_character ON guild_members(character_id);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS guild_territories (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
guild_id UUID NOT NULL REFERENCES guilds(id) ON DELETE CASCADE,
|
|||
|
|
territory_type VARCHAR(32) NOT NULL,
|
|||
|
|
level SMALLINT NOT NULL DEFAULT 1,
|
|||
|
|
upgrade_progress JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
params JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_guild_territories_guild ON guild_territories(guild_id, territory_type);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS guild_diplomacy (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
guild_a_id UUID NOT NULL REFERENCES guilds(id) ON DELETE CASCADE,
|
|||
|
|
guild_b_id UUID NOT NULL REFERENCES guilds(id) ON DELETE CASCADE,
|
|||
|
|
relation VARCHAR(16) NOT NULL, -- allied / at_war / trade / betrayed_cooldown
|
|||
|
|
started_at TIMESTAMPTZ DEFAULT NOW(),
|
|||
|
|
ended_at TIMESTAMPTZ
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_guild_diplomacy_a ON guild_diplomacy(guild_a_id, relation);
|
|||
|
|
CREATE INDEX idx_guild_diplomacy_b ON guild_diplomacy(guild_b_id, relation);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS guild_warehouses (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
guild_id UUID NOT NULL REFERENCES guilds(id) ON DELETE CASCADE,
|
|||
|
|
inventory_id UUID NOT NULL REFERENCES inventories(id) ON DELETE CASCADE,
|
|||
|
|
deposited_by UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
deposit_type VARCHAR(16) NOT NULL DEFAULT 'common', -- common / tribute / black_eat
|
|||
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_guild_warehouses_guild ON guild_warehouses(guild_id);
|
|||
|
|
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
-- 6. 市场、拍卖与情报
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS market_orders (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
seller_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
seller_guild_id UUID REFERENCES guilds(id) ON DELETE SET NULL,
|
|||
|
|
item_id VARCHAR(64) NOT NULL REFERENCES items(id),
|
|||
|
|
inventory_id UUID NOT NULL REFERENCES inventories(id) ON DELETE CASCADE,
|
|||
|
|
currency_code VARCHAR(32) NOT NULL REFERENCES currencies(code),
|
|||
|
|
unit_price NUMERIC(20,4) NOT NULL,
|
|||
|
|
quantity INT NOT NULL,
|
|||
|
|
total_price NUMERIC(20,4) NOT NULL,
|
|||
|
|
tax_rate NUMERIC(5,4) NOT NULL DEFAULT 0.05,
|
|||
|
|
status VARCHAR(16) NOT NULL DEFAULT 'active', -- active / sold / cancelled / expired
|
|||
|
|
world_tier SMALLINT NOT NULL DEFAULT 1,
|
|||
|
|
listed_at TIMESTAMPTZ DEFAULT NOW(),
|
|||
|
|
expired_at TIMESTAMPTZ,
|
|||
|
|
sold_at TIMESTAMPTZ,
|
|||
|
|
buyer_id UUID REFERENCES characters(id) ON DELETE SET NULL
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_market_orders_search ON market_orders(item_id, status, world_tier);
|
|||
|
|
CREATE INDEX idx_market_orders_seller ON market_orders(seller_id, status);
|
|||
|
|
CREATE INDEX idx_market_orders_listed ON market_orders(listed_at);
|
|||
|
|
CREATE INDEX idx_market_orders_status ON market_orders(status, expired_at);
|
|||
|
|
COMMENT ON TABLE market_orders IS '大表建议:按 listed_at 月分区,保留 6 个月';
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS auctions (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
seller_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
guild_id UUID REFERENCES guilds(id) ON DELETE SET NULL,
|
|||
|
|
auction_type VARCHAR(16) NOT NULL, -- official / organization
|
|||
|
|
item_id VARCHAR(64) NOT NULL REFERENCES items(id),
|
|||
|
|
inventory_id UUID NOT NULL REFERENCES inventories(id) ON DELETE CASCADE,
|
|||
|
|
category VARCHAR(32) NOT NULL, -- rare_bloodline / rare_manual / jade_slip / secret_material / artifact / material
|
|||
|
|
currency_code VARCHAR(32) NOT NULL REFERENCES currencies(code),
|
|||
|
|
start_price NUMERIC(20,4) NOT NULL,
|
|||
|
|
reserve_price NUMERIC(20,4),
|
|||
|
|
min_increment_rate NUMERIC(5,4) NOT NULL DEFAULT 0.05,
|
|||
|
|
deposit_rate NUMERIC(5,4) NOT NULL DEFAULT 0.05,
|
|||
|
|
tax_rate NUMERIC(5,4) NOT NULL DEFAULT 0.05,
|
|||
|
|
status VARCHAR(16) NOT NULL DEFAULT 'preparing', -- preparing / active / extended / sold / expired / robbed
|
|||
|
|
started_at TIMESTAMPTZ,
|
|||
|
|
ended_at TIMESTAMPTZ,
|
|||
|
|
is_anonymous BOOLEAN NOT NULL DEFAULT false,
|
|||
|
|
access_type VARCHAR(16) NOT NULL DEFAULT 'public',
|
|||
|
|
risk_type VARCHAR(16) NOT NULL DEFAULT 'none', -- rare_robbable / none
|
|||
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_auctions_list ON auctions(status, auction_type, ended_at);
|
|||
|
|
CREATE INDEX idx_auctions_seller ON auctions(seller_id);
|
|||
|
|
CREATE INDEX idx_auctions_started ON auctions(started_at);
|
|||
|
|
CREATE INDEX idx_auctions_guild ON auctions(guild_id, status);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS auction_bids (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
auction_id UUID NOT NULL REFERENCES auctions(id) ON DELETE CASCADE,
|
|||
|
|
bidder_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
amount NUMERIC(20,4) NOT NULL,
|
|||
|
|
deposit_paid NUMERIC(20,4) NOT NULL DEFAULT 0,
|
|||
|
|
is_auto_bid BOOLEAN NOT NULL DEFAULT false,
|
|||
|
|
auto_max_amount NUMERIC(20,4),
|
|||
|
|
bid_at TIMESTAMPTZ DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_auction_bids_auction ON auction_bids(auction_id, bid_at);
|
|||
|
|
CREATE INDEX idx_auction_bids_bidder ON auction_bids(bidder_id, bid_at);
|
|||
|
|
COMMENT ON TABLE auction_bids IS '大表建议:与 auctions 对齐,按 bid_at 月分区,保留 6 个月';
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS auction_blacklist_records (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
guild_id UUID NOT NULL REFERENCES guilds(id) ON DELETE CASCADE,
|
|||
|
|
auction_id UUID NOT NULL REFERENCES auctions(id) ON DELETE CASCADE,
|
|||
|
|
is_exposed BOOLEAN NOT NULL DEFAULT false,
|
|||
|
|
exposed_at TIMESTAMPTZ,
|
|||
|
|
exposure_type VARCHAR(16), -- report / arbitration / heaven_sense
|
|||
|
|
punishment_level SMALLINT,
|
|||
|
|
reputation_delta INT,
|
|||
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_auction_blacklist_guild ON auction_blacklist_records(guild_id);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS intelligence_orders (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
seller_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
buyer_id UUID REFERENCES characters(id) ON DELETE SET NULL,
|
|||
|
|
intel_type VARCHAR(32) NOT NULL, -- resource / event / location / bounty_clue / instance_entry / unique_skill_clue
|
|||
|
|
target_id UUID,
|
|||
|
|
target_world_tier SMALLINT NOT NULL DEFAULT 1,
|
|||
|
|
content_summary VARCHAR(256),
|
|||
|
|
detail_data JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
currency_code VARCHAR(32) NOT NULL REFERENCES currencies(code),
|
|||
|
|
price NUMERIC(20,4) NOT NULL,
|
|||
|
|
purchase_count SMALLINT NOT NULL DEFAULT 0,
|
|||
|
|
max_purchase SMALLINT NOT NULL DEFAULT 1,
|
|||
|
|
status VARCHAR(16) NOT NULL DEFAULT 'active', -- active / sold_out / expired
|
|||
|
|
cooldown_until TIMESTAMPTZ,
|
|||
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_intelligence_type ON intelligence_orders(intel_type, status);
|
|||
|
|
CREATE INDEX idx_intelligence_target_tier ON intelligence_orders(target_world_tier, status);
|
|||
|
|
CREATE INDEX idx_intelligence_seller ON intelligence_orders(seller_id);
|
|||
|
|
CREATE INDEX idx_intelligence_created ON intelligence_orders(created_at);
|
|||
|
|
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
-- 7. 弟子系统
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS disciples (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
owner_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
guild_id UUID REFERENCES guilds(id) ON DELETE SET NULL,
|
|||
|
|
name VARCHAR(64) NOT NULL,
|
|||
|
|
race_id VARCHAR(32) NOT NULL,
|
|||
|
|
quality VARCHAR(16) NOT NULL DEFAULT 'common', -- common / fine / excellent / perfect / immortal
|
|||
|
|
profession VARCHAR(32),
|
|||
|
|
stats JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
skills JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
equipment JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
daily_task_quota_min INT NOT NULL DEFAULT 120,
|
|||
|
|
death_rate_modifier NUMERIC(5,4) NOT NULL DEFAULT 0,
|
|||
|
|
status VARCHAR(16) NOT NULL DEFAULT 'active', -- active / dead / dispatched / insurance_pending
|
|||
|
|
tombstone_data JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|||
|
|
died_at TIMESTAMPTZ
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_disciples_owner ON disciples(owner_id, status);
|
|||
|
|
CREATE INDEX idx_disciples_guild ON disciples(guild_id);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS disciple_missions (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
disciple_id UUID NOT NULL REFERENCES disciples(id) ON DELETE CASCADE,
|
|||
|
|
owner_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
contract_id UUID, -- FK deferred to contracts creation below
|
|||
|
|
mission_type VARCHAR(16) NOT NULL, -- mercenary / gathering / sect_proxy
|
|||
|
|
difficulty SMALLINT NOT NULL DEFAULT 1,
|
|||
|
|
success_rate NUMERIC(5,4) NOT NULL DEFAULT 0,
|
|||
|
|
death_rate NUMERIC(5,4) NOT NULL DEFAULT 0,
|
|||
|
|
insurance_item_id UUID REFERENCES inventories(id) ON DELETE SET NULL,
|
|||
|
|
result VARCHAR(16) NOT NULL DEFAULT 'pending', -- pending / success / fail / death
|
|||
|
|
rewards JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
started_at TIMESTAMPTZ DEFAULT NOW(),
|
|||
|
|
ended_at TIMESTAMPTZ
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_disciple_missions_disciple ON disciple_missions(disciple_id, result);
|
|||
|
|
CREATE INDEX idx_disciple_missions_owner ON disciple_missions(owner_id, started_at);
|
|||
|
|
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
-- 8. 悬赏、追杀令与佣兵委托
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS contracts (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
contract_type VARCHAR(32) NOT NULL, -- mercenary / limited_time / bounty
|
|||
|
|
publisher_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
publisher_guild_id UUID REFERENCES guilds(id) ON DELETE SET NULL,
|
|||
|
|
difficulty SMALLINT NOT NULL DEFAULT 1,
|
|||
|
|
currency_code VARCHAR(32) NOT NULL REFERENCES currencies(code),
|
|||
|
|
base_reward NUMERIC(20,4) NOT NULL,
|
|||
|
|
max_participants SMALLINT NOT NULL DEFAULT 1,
|
|||
|
|
status VARCHAR(16) NOT NULL DEFAULT 'active', -- active / accepted / completed / failed / expired / cancelled
|
|||
|
|
valid_until TIMESTAMPTZ NOT NULL,
|
|||
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|||
|
|
completed_at TIMESTAMPTZ
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_contracts_publisher ON contracts(publisher_id, contract_type, status);
|
|||
|
|
CREATE INDEX idx_contracts_status_until ON contracts(status, valid_until);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS bounties (
|
|||
|
|
contract_id UUID PRIMARY KEY REFERENCES contracts(id) ON DELETE CASCADE,
|
|||
|
|
bounty_type VARCHAR(16) NOT NULL, -- official_bounty / private_bounty / manhunt
|
|||
|
|
target_id UUID REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
target_world_tier SMALLINT NOT NULL DEFAULT 1,
|
|||
|
|
reward_amount NUMERIC(20,4) NOT NULL,
|
|||
|
|
fee_amount NUMERIC(20,4) NOT NULL DEFAULT 0,
|
|||
|
|
is_anonymous BOOLEAN NOT NULL DEFAULT false,
|
|||
|
|
report_count_today SMALLINT NOT NULL DEFAULT 0,
|
|||
|
|
trigger_probability NUMERIC(5,4) NOT NULL DEFAULT 0,
|
|||
|
|
clues JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
item_inventory_id UUID REFERENCES inventories(id) ON DELETE SET NULL
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_bounties_target ON bounties(target_id, bounty_type, target_world_tier);
|
|||
|
|
CREATE INDEX idx_bounties_type ON bounties(bounty_type, target_world_tier);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS contract_participants (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
contract_id UUID NOT NULL REFERENCES contracts(id) ON DELETE CASCADE,
|
|||
|
|
character_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
participant_type VARCHAR(16) NOT NULL, -- hunter / disciple_proxy / party_member
|
|||
|
|
disciple_id UUID REFERENCES disciples(id) ON DELETE SET NULL,
|
|||
|
|
status VARCHAR(16) NOT NULL DEFAULT 'accepted', -- accepted / active / completed / failed
|
|||
|
|
accepted_at TIMESTAMPTZ DEFAULT NOW(),
|
|||
|
|
completed_at TIMESTAMPTZ
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_contract_participants_contract ON contract_participants(contract_id, status);
|
|||
|
|
CREATE INDEX idx_contract_participants_character ON contract_participants(character_id, status);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS manhunt_records (
|
|||
|
|
bounty_id UUID PRIMARY KEY REFERENCES bounties(contract_id) ON DELETE CASCADE,
|
|||
|
|
original_owner_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
current_holder_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
window_end_at TIMESTAMPTZ NOT NULL,
|
|||
|
|
outcome VARCHAR(16) NOT NULL DEFAULT 'pending', -- pending / returned / black_ate / failed
|
|||
|
|
hunter_choice VARCHAR(16),
|
|||
|
|
compensation_paid NUMERIC(20,4) DEFAULT 0,
|
|||
|
|
chase_right_until TIMESTAMPTZ,
|
|||
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
-- 9. 世界地图、区域、副本与遗迹
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS world_layers (
|
|||
|
|
tier SMALLINT PRIMARY KEY,
|
|||
|
|
name VARCHAR(64) NOT NULL,
|
|||
|
|
display_layer SMALLINT NOT NULL DEFAULT 0,
|
|||
|
|
realm_tier SMALLINT NOT NULL DEFAULT 1,
|
|||
|
|
is_pvp_enabled BOOLEAN NOT NULL DEFAULT false,
|
|||
|
|
cross_tier_rules JSONB NOT NULL DEFAULT '{}'
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS maps (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
world_tier SMALLINT NOT NULL REFERENCES world_layers(tier),
|
|||
|
|
name VARCHAR(128) NOT NULL,
|
|||
|
|
map_type VARCHAR(16) NOT NULL DEFAULT 'world', -- world / event / instance / ruin
|
|||
|
|
seed BIGINT,
|
|||
|
|
layout_data JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
is_active BOOLEAN NOT NULL DEFAULT true,
|
|||
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_maps_world_tier ON maps(world_tier, map_type, is_active);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS regions (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
map_id UUID NOT NULL REFERENCES maps(id) ON DELETE CASCADE,
|
|||
|
|
world_tier SMALLINT NOT NULL DEFAULT 1,
|
|||
|
|
name VARCHAR(128) NOT NULL,
|
|||
|
|
theme VARCHAR(32),
|
|||
|
|
is_safe_zone BOOLEAN NOT NULL DEFAULT false,
|
|||
|
|
pvp_rules JSONB NOT NULL DEFAULT '{}'
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_regions_map ON regions(map_id, is_safe_zone);
|
|||
|
|
CREATE INDEX idx_regions_world_tier ON regions(world_tier);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS zones (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
region_id UUID NOT NULL REFERENCES regions(id) ON DELETE CASCADE,
|
|||
|
|
zone_type VARCHAR(16) NOT NULL, -- stronghold / wild / secret / dungeon / ruins
|
|||
|
|
name VARCHAR(128) NOT NULL,
|
|||
|
|
terrain VARCHAR(32),
|
|||
|
|
weather VARCHAR(32),
|
|||
|
|
resource_density SMALLINT NOT NULL DEFAULT 1,
|
|||
|
|
danger_level SMALLINT NOT NULL DEFAULT 1,
|
|||
|
|
rarity VARCHAR(16) NOT NULL DEFAULT 'normal',
|
|||
|
|
seed BIGINT,
|
|||
|
|
generated_data JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
refreshed_at TIMESTAMPTZ DEFAULT NOW(),
|
|||
|
|
expires_at TIMESTAMPTZ
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_zones_region ON zones(region_id, zone_type);
|
|||
|
|
CREATE INDEX idx_zones_expires ON zones(expires_at);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS zone_explorations (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
zone_id UUID NOT NULL REFERENCES zones(id) ON DELETE CASCADE,
|
|||
|
|
character_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
fog_state JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
exploration_count INT NOT NULL DEFAULT 0,
|
|||
|
|
last_entered_at TIMESTAMPTZ,
|
|||
|
|
UNIQUE (zone_id, character_id)
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_zone_explorations_zone ON zone_explorations(zone_id);
|
|||
|
|
CREATE INDEX idx_zone_explorations_character ON zone_explorations(character_id);
|
|||
|
|
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
-- 10. 战斗与战报
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS battles (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
battle_type VARCHAR(16) NOT NULL, -- expedition_pve / dungeon_pve / pvp / gvg / bounty / manhunt
|
|||
|
|
world_tier SMALLINT NOT NULL DEFAULT 1,
|
|||
|
|
realm_tier SMALLINT NOT NULL DEFAULT 1,
|
|||
|
|
game_timestamp TIMESTAMPTZ DEFAULT NOW(),
|
|||
|
|
attacker_id UUID REFERENCES characters(id) ON DELETE SET NULL,
|
|||
|
|
defender_id UUID REFERENCES characters(id) ON DELETE SET NULL,
|
|||
|
|
party_a UUID[] NOT NULL DEFAULT '{}',
|
|||
|
|
party_b UUID[] NOT NULL DEFAULT '{}',
|
|||
|
|
status VARCHAR(16) NOT NULL DEFAULT 'in_progress', -- in_progress / completed
|
|||
|
|
result_summary JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_battles_attacker ON battles(attacker_id, created_at);
|
|||
|
|
CREATE INDEX idx_battles_defender ON battles(defender_id, created_at);
|
|||
|
|
CREATE INDEX idx_battles_type_status ON battles(battle_type, status);
|
|||
|
|
CREATE INDEX idx_battles_realm ON battles(world_tier, realm_tier, created_at);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS battle_logs (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
battle_id UUID UNIQUE NOT NULL REFERENCES battles(id) ON DELETE CASCADE,
|
|||
|
|
report JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
special_events JSONB NOT NULL DEFAULT '[]',
|
|||
|
|
drops JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_battle_logs_created ON battle_logs(created_at);
|
|||
|
|
CREATE INDEX idx_battle_logs_report_gin ON battle_logs USING GIN (report jsonb_path_ops);
|
|||
|
|
COMMENT ON TABLE battle_logs IS '大表建议:按 created_at 周分区,保留 8 周(可用 pg_partman)';
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS player_kills (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
killer_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
victim_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
battle_id UUID REFERENCES battles(id) ON DELETE SET NULL,
|
|||
|
|
world_tier SMALLINT NOT NULL DEFAULT 1,
|
|||
|
|
is_malice BOOLEAN NOT NULL DEFAULT false,
|
|||
|
|
karma_delta INT NOT NULL DEFAULT 0,
|
|||
|
|
crime_delta INT NOT NULL DEFAULT 0,
|
|||
|
|
loot_taken JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_player_kills_killer ON player_kills(killer_id);
|
|||
|
|
CREATE INDEX idx_player_kills_victim ON player_kills(victim_id);
|
|||
|
|
CREATE INDEX idx_player_kills_world ON player_kills(world_tier, created_at);
|
|||
|
|
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
-- 11. 副本、遗迹(依赖 battles)
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS instances (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
zone_id UUID NOT NULL REFERENCES zones(id) ON DELETE CASCADE,
|
|||
|
|
instance_type VARCHAR(16) NOT NULL, -- permanent / random / ruin / event
|
|||
|
|
theme VARCHAR(32),
|
|||
|
|
world_tier SMALLINT NOT NULL DEFAULT 1,
|
|||
|
|
recommended_realm_tier SMALLINT NOT NULL DEFAULT 1,
|
|||
|
|
generated_layout JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
affixes JSONB NOT NULL DEFAULT '[]',
|
|||
|
|
max_parties SMALLINT NOT NULL DEFAULT 1,
|
|||
|
|
expires_at TIMESTAMPTZ,
|
|||
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_instances_world_tier ON instances(world_tier, instance_type, expires_at);
|
|||
|
|
CREATE INDEX idx_instances_zone ON instances(zone_id);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS instance_runs (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
instance_id UUID NOT NULL REFERENCES instances(id) ON DELETE CASCADE,
|
|||
|
|
party_leader_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
party_members UUID[] NOT NULL DEFAULT '{}',
|
|||
|
|
difficulty_coefficient NUMERIC(6,4) NOT NULL DEFAULT 1.0,
|
|||
|
|
status VARCHAR(16) NOT NULL DEFAULT 'in_progress', -- in_progress / completed / failed / abandoned
|
|||
|
|
battle_id UUID REFERENCES battles(id) ON DELETE SET NULL,
|
|||
|
|
consumed_keys SMALLINT NOT NULL DEFAULT 0,
|
|||
|
|
started_at TIMESTAMPTZ DEFAULT NOW(),
|
|||
|
|
ended_at TIMESTAMPTZ
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_instance_runs_instance ON instance_runs(instance_id, status);
|
|||
|
|
CREATE INDEX idx_instance_runs_leader ON instance_runs(party_leader_id, started_at);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS instance_loot (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
run_id UUID NOT NULL REFERENCES instance_runs(id) ON DELETE CASCADE,
|
|||
|
|
character_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
item_id VARCHAR(64) NOT NULL REFERENCES items(id),
|
|||
|
|
inventory_id UUID REFERENCES inventories(id) ON DELETE SET NULL,
|
|||
|
|
currency_code VARCHAR(32) REFERENCES currencies(code),
|
|||
|
|
currency_amount NUMERIC(20,4) DEFAULT 0,
|
|||
|
|
is_resonance_copy BOOLEAN NOT NULL DEFAULT false,
|
|||
|
|
completeness NUMERIC(5,4) DEFAULT 1.0,
|
|||
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_instance_loot_run ON instance_loot(run_id);
|
|||
|
|
CREATE INDEX idx_instance_loot_character ON instance_loot(character_id);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS world_ruin_records (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
source_character_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
source_world_tier SMALLINT NOT NULL,
|
|||
|
|
region_id UUID NOT NULL REFERENCES regions(id) ON DELETE CASCADE,
|
|||
|
|
zone_id UUID NOT NULL REFERENCES zones(id) ON DELETE CASCADE,
|
|||
|
|
instance_id UUID REFERENCES instances(id) ON DELETE SET NULL,
|
|||
|
|
richness_score NUMERIC(8,2) NOT NULL DEFAULT 0,
|
|||
|
|
snapshot_data JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
total_extractable NUMERIC(6,4) NOT NULL DEFAULT 0,
|
|||
|
|
extracted_ratio NUMERIC(6,4) NOT NULL DEFAULT 0,
|
|||
|
|
status VARCHAR(16) NOT NULL DEFAULT 'active',
|
|||
|
|
opened_at TIMESTAMPTZ DEFAULT NOW(),
|
|||
|
|
expires_at TIMESTAMPTZ
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_world_ruin_source ON world_ruin_records(source_character_id);
|
|||
|
|
CREATE INDEX idx_world_ruin_region ON world_ruin_records(region_id, status);
|
|||
|
|
CREATE INDEX idx_world_ruin_expires ON world_ruin_records(status, expires_at);
|
|||
|
|
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
-- 12. 渡劫记录
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS tribulation_records (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
character_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
realm_tier SMALLINT NOT NULL,
|
|||
|
|
minor_realm SMALLINT NOT NULL,
|
|||
|
|
tribulation_type VARCHAR(16) NOT NULL, -- normal / heart_devil / qi_deviation / chaos / heti
|
|||
|
|
base_success_rate NUMERIC(5,4) NOT NULL,
|
|||
|
|
modified_success_rate NUMERIC(5,4) NOT NULL,
|
|||
|
|
helper_ids UUID[] NOT NULL DEFAULT '{}',
|
|||
|
|
result VARCHAR(16) NOT NULL, -- success / fail / backlash / death
|
|||
|
|
penalties JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
drops_on_success JSONB NOT NULL DEFAULT '[]',
|
|||
|
|
san_snapshot SMALLINT NOT NULL DEFAULT 100,
|
|||
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_tribulation_character ON tribulation_records(character_id, created_at);
|
|||
|
|
CREATE INDEX idx_tribulation_realm ON tribulation_records(realm_tier, created_at);
|
|||
|
|
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
-- 13. 社交关系
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS social_relations (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
character_a_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
character_b_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
relation_type VARCHAR(16) NOT NULL, -- friend / companion / master / apprentice / enemy
|
|||
|
|
intimacy INT NOT NULL DEFAULT 0,
|
|||
|
|
status VARCHAR(16) NOT NULL DEFAULT 'active', -- active / cooldown / dissolved
|
|||
|
|
cooldown_until TIMESTAMPTZ,
|
|||
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|||
|
|
dissolved_at TIMESTAMPTZ,
|
|||
|
|
UNIQUE (character_a_id, character_b_id, relation_type)
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_social_relations_a ON social_relations(character_a_id, relation_type, status);
|
|||
|
|
CREATE INDEX idx_social_relations_b ON social_relations(character_b_id, relation_type, status);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS lovers (
|
|||
|
|
relation_id UUID PRIMARY KEY REFERENCES social_relations(id) ON DELETE CASCADE,
|
|||
|
|
resonance INT NOT NULL DEFAULT 0,
|
|||
|
|
shared_residence_id UUID REFERENCES guild_territories(id) ON DELETE SET NULL,
|
|||
|
|
combined_skill_id UUID REFERENCES character_skills(id) ON DELETE SET NULL,
|
|||
|
|
vow_path VARCHAR(16),
|
|||
|
|
teleport_cooldown_until TIMESTAMPTZ,
|
|||
|
|
mutual_benefits JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS sworn_brothers (
|
|||
|
|
relation_id UUID PRIMARY KEY REFERENCES social_relations(id) ON DELETE CASCADE,
|
|||
|
|
group_id UUID UNIQUE NOT NULL DEFAULT gen_random_uuid(),
|
|||
|
|
member_order SMALLINT NOT NULL DEFAULT 0,
|
|||
|
|
shared_mission_slots JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
group_buffs JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
flag_zone_id UUID REFERENCES zones(id) ON DELETE SET NULL,
|
|||
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS reputation_records (
|
|||
|
|
id BIGSERIAL PRIMARY KEY,
|
|||
|
|
character_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
source_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
source_type VARCHAR(16) NOT NULL, -- trade / mercenary / master / party / report
|
|||
|
|
delta INT NOT NULL DEFAULT 0,
|
|||
|
|
tag VARCHAR(32),
|
|||
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_reputation_character ON reputation_records(character_id, created_at);
|
|||
|
|
CREATE INDEX idx_reputation_source ON reputation_records(source_id, created_at);
|
|||
|
|
COMMENT ON TABLE reputation_records IS '大表建议:按 created_at 月分区,保留 6 个月';
|
|||
|
|
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
-- 14. 配置与审计
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS nacos_configs (
|
|||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|||
|
|
config_key VARCHAR(128) UNIQUE NOT NULL,
|
|||
|
|
namespace VARCHAR(64) NOT NULL,
|
|||
|
|
value JSONB NOT NULL DEFAULT '{}',
|
|||
|
|
version INT NOT NULL DEFAULT 1,
|
|||
|
|
is_grayscale BOOLEAN NOT NULL DEFAULT false,
|
|||
|
|
grayscale_ratio NUMERIC(5,4) NOT NULL DEFAULT 0,
|
|||
|
|
effective_from TIMESTAMPTZ,
|
|||
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|||
|
|
updated_at TIMESTAMPTZ DEFAULT NOW()
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
CREATE INDEX idx_nacos_configs_namespace ON nacos_configs(namespace, config_key);
|
|||
|
|
|
|||
|
|
CREATE TABLE IF NOT EXISTS daily_reset_tracking (
|
|||
|
|
character_id UUID NOT NULL REFERENCES characters(id) ON DELETE CASCADE,
|
|||
|
|
reset_date DATE NOT NULL,
|
|||
|
|
report_count_used SMALLINT NOT NULL DEFAULT 0,
|
|||
|
|
instance_count_used SMALLINT NOT NULL DEFAULT 0,
|
|||
|
|
ruin_count_used SMALLINT NOT NULL DEFAULT 0,
|
|||
|
|
double_cultivation_minutes SMALLINT NOT NULL DEFAULT 0,
|
|||
|
|
fishing_games SMALLINT NOT NULL DEFAULT 0,
|
|||
|
|
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
|||
|
|
PRIMARY KEY (character_id, reset_date)
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
-- 14. 延迟外键约束(解决建表顺序依赖)
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
ALTER TABLE guilds ADD CONSTRAINT fk_guilds_region
|
|||
|
|
FOREIGN KEY (region_id) REFERENCES regions(id) ON DELETE SET NULL;
|
|||
|
|
ALTER TABLE guilds ADD CONSTRAINT fk_guilds_zone
|
|||
|
|
FOREIGN KEY (zone_id) REFERENCES zones(id) ON DELETE SET NULL;
|
|||
|
|
|
|||
|
|
ALTER TABLE disciple_missions ADD CONSTRAINT fk_disciple_missions_contract
|
|||
|
|
FOREIGN KEY (contract_id) REFERENCES contracts(id) ON DELETE SET NULL;
|
|||
|
|
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
-- 15. 参考数据 seed
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
|
|||
|
|
INSERT INTO race_templates (id, name, category, can_create, description) VALUES
|
|||
|
|
('human', '人族', 'common', false, '默认不可创建,可通过转化获得'),
|
|||
|
|
('tiger_yao', '虎妖', 'common', true, '妖族分支'),
|
|||
|
|
('wolf_yao', '狼妖', 'common', true, '妖族分支'),
|
|||
|
|
('elf_light', '光精灵', 'common', true, '精灵族分支'),
|
|||
|
|
('elf_dark', '暗精灵', 'common', true, '精灵族分支'),
|
|||
|
|
('demon_blood', '魔血族', 'common', true, '魔族分支'),
|
|||
|
|
('ghost_ethereal', '幽魂族', 'common', true, '鬼族分支'),
|
|||
|
|
('deep_one', '深潜裔', 'rare', true, '稀有血统,多分支进化'),
|
|||
|
|
('dragon_blood', '龙血族', 'rare', true, '稀有种族'),
|
|||
|
|
('chaos_heritage', '混沌裔', 'rare', true, '稀有种族'),
|
|||
|
|
('giant', '巨人族', 'rare', true, '稀有种族')
|
|||
|
|
ON CONFLICT (id) DO NOTHING;
|
|||
|
|
|
|||
|
|
INSERT INTO realms (tier, minor_realm_max, name, world_tier, main_currency_code, is_tribulation_required, base_success_rate, attr_growth_template) VALUES
|
|||
|
|
(1, 3, '炼气期', 1, 'copper', false, 1.0, '{"hp":10,"atk":2,"def":1}'),
|
|||
|
|
(2, 3, '筑基期', 2, 'copper', true, 0.55, '{"hp":20,"atk":4,"def":2}'),
|
|||
|
|
(3, 3, '金丹期', 3, 'spirit_stone_low', true, 0.50, '{"hp":35,"atk":7,"def":4}'),
|
|||
|
|
(4, 3, '元婴期', 4, 'soul_crystal', true, 0.45, '{"hp":55,"atk":11,"def":6}'),
|
|||
|
|
(5, 3, '化神期', 5, 'immortal_crystal', true, 0.40, '{"hp":80,"atk":16,"def":9}'),
|
|||
|
|
(6, 3, '合体期', 6, 'chaos_crystal', true, 0.35, '{"hp":110,"atk":22,"def":12}')
|
|||
|
|
ON CONFLICT (tier) DO NOTHING;
|
|||
|
|
|
|||
|
|
INSERT INTO world_layers (tier, name, display_layer, realm_tier, is_pvp_enabled, cross_tier_rules) VALUES
|
|||
|
|
(1, '种族出生地', 0, 1, false, '{}'),
|
|||
|
|
(2, '洪荒主陆', 1, 2, true, '{}'),
|
|||
|
|
(3, '洪荒腹地', 2, 3, true, '{}'),
|
|||
|
|
(4, '太古秘境', 3, 4, true, '{}'),
|
|||
|
|
(5, '混沌之渊·化神域', 4, 5, true, '{}'),
|
|||
|
|
(6, '混沌之渊·合体域', 5, 6, true, '{}')
|
|||
|
|
ON CONFLICT (tier) DO NOTHING;
|
|||
|
|
|
|||
|
|
INSERT INTO currencies (code, name, world_tier, is_premium, exchange_rules) VALUES
|
|||
|
|
('copper', '铜钱', 1, false, '{}'),
|
|||
|
|
('silver', '银两', 2, false, '{}'),
|
|||
|
|
('spirit_stone_low', '下品灵石', 3, false, '{}'),
|
|||
|
|
('spirit_stone_mid', '中品灵石', 3, false, '{}'),
|
|||
|
|
('soul_crystal', '魂晶', 4, false, '{}'),
|
|||
|
|
('immortal_crystal', '仙晶', 5, false, '{}'),
|
|||
|
|
('chaos_crystal', '混沌灵石', 6, false, '{}'),
|
|||
|
|
('purple_gas', '鸿蒙紫气', 1, true, '{}')
|
|||
|
|
ON CONFLICT (code) DO NOTHING;
|
|||
|
|
|
|||
|
|
--------------------------------------------------------------------------------
|
|||
|
|
-- 自检提示(可选):
|
|||
|
|
-- psql -U postgres -d honghuang -f database/migrations/001_init_schema.up.sql
|
|||
|
|
--------------------------------------------------------------------------------
|