server-master/scripts/Database/import-parser-data.ps1

232 lines
9.9 KiB
PowerShell

param(
[string]$DbContainer = "wingsemu-postgres",
[string]$DbName = "game",
[string]$DbUser = "postgres",
[string]$ConfigRoot = "config"
)
$ErrorActionPreference = 'Stop'
$root = Split-Path -Parent (Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Path))
Set-Location $root
$configPath = Join-Path $root $ConfigRoot
if (-not (Test-Path $configPath)) { throw "Config path not found: $configPath" }
$maps = @()
$mapFlags = @()
$portals = @()
$npcs = @()
$monsters = @()
function To-IntOrNull($v) {
if ([string]::IsNullOrWhiteSpace($v)) { return $null }
$v = ($v -split '#')[0].Trim()
if ($v -match '^-?\d+$') { return [int]$v }
return $null
}
function SqlEsc([string]$s) {
if ($null -eq $s) { return 'NULL' }
return "'" + ($s -replace "'","''") + "'"
}
function SqlNum($n) {
if ($null -eq $n) { return 'NULL' }
return [string]$n
}
function Read-NonCommentLines([string]$file) {
Get-Content $file | ForEach-Object { $_.TrimEnd() } | Where-Object { $_ -notmatch '^\s*#' }
}
# -------- maps --------
Get-ChildItem (Join-Path $configPath 'maps') -File -ErrorAction SilentlyContinue | ForEach-Object {
$lines = Read-NonCommentLines $_.FullName
$current = $null
$inFlags = $false
foreach ($line in $lines) {
if ($line -match '^\s*-\s*map_id\s*:\s*(.+)$') {
if ($current) { $maps += $current }
$current = [ordered]@{ map_id = To-IntOrNull $matches[1]; map_vnum = $null; map_name_id = $null; map_music_id = $null; flags = @() }
$inFlags = $false
continue
}
if (-not $current) { continue }
if ($line -match '^\s*flags\s*:') { $inFlags = $true; continue }
if ($inFlags -and $line -match '^\s*-\s*([A-Z0-9_]+)\s*$') {
$current.flags += $matches[1]
continue
}
if ($line -match '^\s*map_vnum\s*:\s*(.+)$') { $current.map_vnum = To-IntOrNull $matches[1]; $inFlags=$false; continue }
if ($line -match '^\s*map_name_id\s*:\s*(.+)$') { $current.map_name_id = To-IntOrNull $matches[1]; $inFlags=$false; continue }
if ($line -match '^\s*map_music_id\s*:\s*(.+)$') { $current.map_music_id = To-IntOrNull $matches[1]; $inFlags=$false; continue }
}
if ($current) { $maps += $current }
}
foreach ($m in $maps) {
foreach ($f in $m.flags) {
$mapFlags += [ordered]@{ map_id = $m.map_id; flag = $f }
}
}
# -------- portals --------
Get-ChildItem (Join-Path $configPath 'map_portals') -File -ErrorAction SilentlyContinue | ForEach-Object {
$lines = Read-NonCommentLines $_.FullName
$current = $null
foreach ($line in $lines) {
if ($line -match '^\s*-\s*destination_map_id\s*:\s*(.+)$') {
if ($current) { $portals += $current }
$current = [ordered]@{
destination_map_id = To-IntOrNull $matches[1]
destination_map_x = $null
destination_map_y = $null
source_map_id = $null
source_map_x = $null
source_map_y = $null
type = $null
}
continue
}
if (-not $current) { continue }
if ($line -match '^\s*destination_map_x\s*:\s*(.+)$') { $current.destination_map_x = To-IntOrNull $matches[1]; continue }
if ($line -match '^\s*destination_map_y\s*:\s*(.+)$') { $current.destination_map_y = To-IntOrNull $matches[1]; continue }
if ($line -match '^\s*source_map_id\s*:\s*(.+)$') { $current.source_map_id = To-IntOrNull $matches[1]; continue }
if ($line -match '^\s*source_map_x\s*:\s*(.+)$') { $current.source_map_x = To-IntOrNull $matches[1]; continue }
if ($line -match '^\s*source_map_y\s*:\s*(.+)$') { $current.source_map_y = To-IntOrNull $matches[1]; continue }
if ($line -match '^\s*type\s*:\s*(.+)$') { $current.type = To-IntOrNull $matches[1]; continue }
}
if ($current) { $portals += $current }
}
# -------- npcs --------
Get-ChildItem (Join-Path $configPath 'map_npc_placement') -File -ErrorAction SilentlyContinue | ForEach-Object {
$lines = Read-NonCommentLines $_.FullName
$mapId = $null
$current = $null
foreach ($line in $lines) {
if ($line -match '^\s*map_id\s*:\s*(.+)$') { $mapId = To-IntOrNull $matches[1]; continue }
if ($line -match '^\s*-\s*map_npc_id\s*:\s*(.+)$') {
if ($current) { $npcs += $current }
$current = [ordered]@{ map_id=$mapId; map_npc_id=To-IntOrNull $matches[1]; vnum=$null; pos_x=$null; pos_y=$null; effect_vnum=$null; effect_delay=$null; dialog_id=$null; direction_facing=$null }
continue
}
if (-not $current) { continue }
if ($line -match '^\s*vnum\s*:\s*(.+)$') { $current.vnum = To-IntOrNull $matches[1]; continue }
if ($line -match '^\s*pos_x\s*:\s*(.+)$') { $current.pos_x = To-IntOrNull $matches[1]; continue }
if ($line -match '^\s*pos_y\s*:\s*(.+)$') { $current.pos_y = To-IntOrNull $matches[1]; continue }
if ($line -match '^\s*effect_vnum\s*:\s*(.+)$') { $current.effect_vnum = To-IntOrNull $matches[1]; continue }
if ($line -match '^\s*effect_delay\s*:\s*(.+)$') { $current.effect_delay = To-IntOrNull $matches[1]; continue }
if ($line -match '^\s*dialog_id\s*:\s*(.+)$') { $current.dialog_id = To-IntOrNull $matches[1]; continue }
if ($line -match '^\s*direction_facing\s*:\s*(.+)$') { $current.direction_facing = To-IntOrNull $matches[1]; continue }
}
if ($current) { $npcs += $current }
}
# -------- monsters --------
Get-ChildItem (Join-Path $configPath 'map_monster_placement') -File -ErrorAction SilentlyContinue | ForEach-Object {
$lines = Read-NonCommentLines $_.FullName
$mapId = $null
$current = $null
foreach ($line in $lines) {
if ($line -match '^\s*map_id\s*:\s*(.+)$') { $mapId = To-IntOrNull $matches[1]; continue }
if ($line -match '^\s*-\s*map_monster_id\s*:\s*(.+)$') {
if ($current) { $monsters += $current }
$current = [ordered]@{ map_id=$mapId; map_monster_id=To-IntOrNull $matches[1]; vnum=$null; map_x=$null; map_y=$null; position=$null; can_move=$null }
continue
}
if (-not $current) { continue }
if ($line -match '^\s*vnum\s*:\s*(.+)$') { $current.vnum = To-IntOrNull $matches[1]; continue }
if ($line -match '^\s*map_x\s*:\s*(.+)$') { $current.map_x = To-IntOrNull $matches[1]; continue }
if ($line -match '^\s*map_y\s*:\s*(.+)$') { $current.map_y = To-IntOrNull $matches[1]; continue }
if ($line -match '^\s*position\s*:\s*(.+)$') { $current.position = To-IntOrNull $matches[1]; continue }
if ($line -match '^\s*can_move\s*:\s*(.+)$') { $current.can_move = ($matches[1].Trim().ToLower() -eq 'true'); continue }
}
if ($current) { $monsters += $current }
}
$sql = New-Object System.Text.StringBuilder
[void]$sql.AppendLine("BEGIN;")
[void]$sql.AppendLine(@"
DROP TABLE IF EXISTS server_map_flags;
DROP TABLE IF EXISTS server_maps;
DROP TABLE IF EXISTS map_portals;
DROP TABLE IF EXISTS map_npcs;
DROP TABLE IF EXISTS map_monsters;
CREATE TABLE server_maps (
map_id INT PRIMARY KEY,
map_vnum INT,
map_name_id INT,
map_music_id INT
);
CREATE TABLE server_map_flags (
map_id INT NOT NULL,
flag TEXT NOT NULL,
PRIMARY KEY (map_id, flag)
);
CREATE TABLE map_portals (
id BIGSERIAL PRIMARY KEY,
destination_map_id INT,
destination_map_x INT,
destination_map_y INT,
source_map_id INT,
source_map_x INT,
source_map_y INT,
type INT
);
CREATE TABLE map_npcs (
id BIGSERIAL PRIMARY KEY,
map_npc_id INT,
map_id INT,
vnum INT,
pos_x INT,
pos_y INT,
effect_vnum INT,
effect_delay INT,
dialog_id INT,
direction_facing INT
);
CREATE TABLE map_monsters (
id BIGSERIAL PRIMARY KEY,
map_monster_id INT,
map_id INT,
vnum INT,
map_x INT,
map_y INT,
position INT,
can_move BOOLEAN
);
"@)
foreach ($m in $maps | Where-Object { $null -ne $_.map_id }) {
[void]$sql.AppendLine("INSERT INTO server_maps(map_id,map_vnum,map_name_id,map_music_id) VALUES ($(SqlNum $m.map_id),$(SqlNum $m.map_vnum),$(SqlNum $m.map_name_id),$(SqlNum $m.map_music_id));")
}
foreach ($f in $mapFlags | Where-Object { $null -ne $_.map_id -and -not [string]::IsNullOrWhiteSpace($_.flag) }) {
[void]$sql.AppendLine("INSERT INTO server_map_flags(map_id,flag) VALUES ($(SqlNum $f.map_id),$(SqlEsc $f.flag));")
}
foreach ($p in $portals) {
[void]$sql.AppendLine("INSERT INTO map_portals(destination_map_id,destination_map_x,destination_map_y,source_map_id,source_map_x,source_map_y,type) VALUES ($(SqlNum $p.destination_map_id),$(SqlNum $p.destination_map_x),$(SqlNum $p.destination_map_y),$(SqlNum $p.source_map_id),$(SqlNum $p.source_map_x),$(SqlNum $p.source_map_y),$(SqlNum $p.type));")
}
foreach ($n in $npcs | Where-Object { $null -ne $_.map_npc_id }) {
[void]$sql.AppendLine("INSERT INTO map_npcs(map_npc_id,map_id,vnum,pos_x,pos_y,effect_vnum,effect_delay,dialog_id,direction_facing) VALUES ($(SqlNum $n.map_npc_id),$(SqlNum $n.map_id),$(SqlNum $n.vnum),$(SqlNum $n.pos_x),$(SqlNum $n.pos_y),$(SqlNum $n.effect_vnum),$(SqlNum $n.effect_delay),$(SqlNum $n.dialog_id),$(SqlNum $n.direction_facing));")
}
foreach ($m in $monsters | Where-Object { $null -ne $_.map_monster_id }) {
$mv = if ($null -eq $m.can_move) { 'NULL' } elseif ($m.can_move) { 'TRUE' } else { 'FALSE' }
[void]$sql.AppendLine("INSERT INTO map_monsters(map_monster_id,map_id,vnum,map_x,map_y,position,can_move) VALUES ($(SqlNum $m.map_monster_id),$(SqlNum $m.map_id),$(SqlNum $m.vnum),$(SqlNum $m.map_x),$(SqlNum $m.map_y),$(SqlNum $m.position),$mv);")
}
[void]$sql.AppendLine("COMMIT;")
$tmpSql = Join-Path $env:TEMP "parser_import.sql"
[System.IO.File]::WriteAllText($tmpSql, $sql.ToString())
Get-Content -Raw $tmpSql | docker exec -i $DbContainer psql -v ON_ERROR_STOP=1 -U $DbUser -d $DbName | Out-Host
Write-Host "Imported maps=$($maps.Count) flags=$($mapFlags.Count) portals=$($portals.Count) npcs=$($npcs.Count) monsters=$($monsters.Count)" -ForegroundColor Green