161 行
6.4 KiB
Bash
161 行
6.4 KiB
Bash
|
|
#!/usr/bin/env bash
|
|||
|
|
# 洪荒大陆 · 开发测试数据种子脚本
|
|||
|
|
# 插入:测试玩家、角色、种族状态、境界进度、基础货币
|
|||
|
|
|
|||
|
|
set -euo pipefail
|
|||
|
|
|
|||
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|||
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|||
|
|
|
|||
|
|
# 加载 .env(若存在),也允许通过环境变量直接传入 DATABASE_URL
|
|||
|
|
if [ -f "$PROJECT_ROOT/.env" ]; then
|
|||
|
|
set -a
|
|||
|
|
# shellcheck source=/dev/null
|
|||
|
|
source "$PROJECT_ROOT/.env"
|
|||
|
|
set +a
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
if [ -z "${DATABASE_URL:-}" ]; then
|
|||
|
|
echo "Error: DATABASE_URL is not set. Please create .env from .env.example or export DATABASE_URL." >&2
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
if ! command -v psql >/dev/null 2>&1; then
|
|||
|
|
echo "Error: psql command not found. Please install PostgreSQL client." >&2
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# 等待数据库可达
|
|||
|
|
wait_for_db() {
|
|||
|
|
local timeout="${DB_WAIT_TIMEOUT:-30}"
|
|||
|
|
local elapsed=0
|
|||
|
|
echo "Waiting for database to be available..."
|
|||
|
|
until psql "$DATABASE_URL" -c "SELECT 1;" >/dev/null 2>&1; do
|
|||
|
|
if [ "$elapsed" -ge "$timeout" ]; then
|
|||
|
|
echo "Error: database not available after ${timeout}s" >&2
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
printf "."
|
|||
|
|
sleep 1
|
|||
|
|
elapsed=$((elapsed + 1))
|
|||
|
|
done
|
|||
|
|
echo " OK"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
wait_for_db
|
|||
|
|
|
|||
|
|
# 确保静态参考数据已存在(迁移 up.sql 已包含,此处做幂等兜底)
|
|||
|
|
echo "Ensuring static reference data exists..."
|
|||
|
|
psql "$DATABASE_URL" -v ON_ERROR_STOP=1 <<'EOF'
|
|||
|
|
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 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;
|
|||
|
|
EOF
|
|||
|
|
|
|||
|
|
# 插入开发测试账号与角色
|
|||
|
|
psql "$DATABASE_URL" -v ON_ERROR_STOP=1 <<'EOF'
|
|||
|
|
DO $$
|
|||
|
|
DECLARE
|
|||
|
|
v_player_id UUID;
|
|||
|
|
v_character_id UUID;
|
|||
|
|
BEGIN
|
|||
|
|
-- 测试玩家甲
|
|||
|
|
SELECT id INTO v_player_id FROM players WHERE device_id_hash = 'dev_seed_001';
|
|||
|
|
IF v_player_id IS NULL THEN
|
|||
|
|
INSERT INTO players (id, nakama_user_id, platform, device_id_hash, status)
|
|||
|
|
VALUES (gen_random_uuid(), gen_random_uuid(), 'guest', 'dev_seed_001', 'active')
|
|||
|
|
RETURNING id INTO v_player_id;
|
|||
|
|
END IF;
|
|||
|
|
|
|||
|
|
SELECT id INTO v_character_id FROM characters WHERE name = '测试修士·甲';
|
|||
|
|
IF v_character_id IS NULL THEN
|
|||
|
|
INSERT INTO characters (
|
|||
|
|
id, player_id, name, race_id, birth_race_id, birth_world_tier, world_tier, realm_tier, minor_realm,
|
|||
|
|
level, exp, power, status, base_stats, battle_stats, san_current, san_max
|
|||
|
|
) VALUES (
|
|||
|
|
gen_random_uuid(), v_player_id, '测试修士·甲', 'tiger_yao', 'tiger_yao', 1, 1, 1, 1,
|
|||
|
|
1, 0, 100, 'active',
|
|||
|
|
'{"str":12,"vit":11,"wis":9,"agi":13,"spi":10,"luk":10}'::jsonb,
|
|||
|
|
'{"hp_max":1100,"atk":110,"def":55,"speed":105}'::jsonb,
|
|||
|
|
100, 100
|
|||
|
|
)
|
|||
|
|
RETURNING id INTO v_character_id;
|
|||
|
|
END IF;
|
|||
|
|
|
|||
|
|
IF NOT EXISTS (SELECT 1 FROM character_race_states WHERE character_id = v_character_id) THEN
|
|||
|
|
INSERT INTO character_race_states (character_id, main_race_id, is_rare_race)
|
|||
|
|
VALUES (v_character_id, 'tiger_yao', false);
|
|||
|
|
END IF;
|
|||
|
|
|
|||
|
|
IF NOT EXISTS (SELECT 1 FROM character_realms WHERE character_id = v_character_id AND is_current = true) THEN
|
|||
|
|
INSERT INTO character_realms (id, character_id, realm_tier, max_minor_reached, exp_in_tier, is_current)
|
|||
|
|
VALUES (gen_random_uuid(), v_character_id, 1, 1, 0, true);
|
|||
|
|
END IF;
|
|||
|
|
|
|||
|
|
INSERT INTO currency_balances (character_id, currency_code, amount, total_earned)
|
|||
|
|
VALUES
|
|||
|
|
(v_character_id, 'copper', 10000, 10000),
|
|||
|
|
(v_character_id, 'purple_gas', 100, 100)
|
|||
|
|
ON CONFLICT (character_id, currency_code) DO UPDATE
|
|||
|
|
SET amount = EXCLUDED.amount, total_earned = EXCLUDED.total_earned, updated_at = NOW();
|
|||
|
|
|
|||
|
|
-- 测试玩家乙(用于 PVP/结义/道侣等双人玩法验证)
|
|||
|
|
SELECT id INTO v_player_id FROM players WHERE device_id_hash = 'dev_seed_002';
|
|||
|
|
IF v_player_id IS NULL THEN
|
|||
|
|
INSERT INTO players (id, nakama_user_id, platform, device_id_hash, status)
|
|||
|
|
VALUES (gen_random_uuid(), gen_random_uuid(), 'guest', 'dev_seed_002', 'active')
|
|||
|
|
RETURNING id INTO v_player_id;
|
|||
|
|
END IF;
|
|||
|
|
|
|||
|
|
SELECT id INTO v_character_id FROM characters WHERE name = '测试修士·乙';
|
|||
|
|
IF v_character_id IS NULL THEN
|
|||
|
|
INSERT INTO characters (
|
|||
|
|
id, player_id, name, race_id, birth_race_id, birth_world_tier, world_tier, realm_tier, minor_realm,
|
|||
|
|
level, exp, power, status, base_stats, battle_stats, san_current, san_max
|
|||
|
|
) VALUES (
|
|||
|
|
gen_random_uuid(), v_player_id, '测试修士·乙', 'elf_light', 'elf_light', 1, 1, 1, 2,
|
|||
|
|
5, 450, 120, 'active',
|
|||
|
|
'{"str":9,"vit":10,"wis":14,"agi":12,"spi":12,"luk":11}'::jsonb,
|
|||
|
|
'{"hp_max":1050,"atk":95,"def":60,"speed":115}'::jsonb,
|
|||
|
|
100, 100
|
|||
|
|
)
|
|||
|
|
RETURNING id INTO v_character_id;
|
|||
|
|
END IF;
|
|||
|
|
|
|||
|
|
IF NOT EXISTS (SELECT 1 FROM character_race_states WHERE character_id = v_character_id) THEN
|
|||
|
|
INSERT INTO character_race_states (character_id, main_race_id, is_rare_race)
|
|||
|
|
VALUES (v_character_id, 'elf_light', false);
|
|||
|
|
END IF;
|
|||
|
|
|
|||
|
|
IF NOT EXISTS (SELECT 1 FROM character_realms WHERE character_id = v_character_id AND is_current = true) THEN
|
|||
|
|
INSERT INTO character_realms (id, character_id, realm_tier, max_minor_reached, exp_in_tier, is_current)
|
|||
|
|
VALUES (gen_random_uuid(), v_character_id, 1, 2, 450, true);
|
|||
|
|
END IF;
|
|||
|
|
|
|||
|
|
INSERT INTO currency_balances (character_id, currency_code, amount, total_earned)
|
|||
|
|
VALUES
|
|||
|
|
(v_character_id, 'copper', 5000, 5000),
|
|||
|
|
(v_character_id, 'purple_gas', 50, 50)
|
|||
|
|
ON CONFLICT (character_id, currency_code) DO UPDATE
|
|||
|
|
SET amount = EXCLUDED.amount, total_earned = EXCLUDED.total_earned, updated_at = NOW();
|
|||
|
|
END $$;
|
|||
|
|
EOF
|
|||
|
|
|
|||
|
|
echo "Seed data inserted successfully."
|