Paradox.Modding.Stellaris.psm1

function ConvertTo-PdsBuilding {
    <#
    .SYNOPSIS
        Converts building configuration files into building mod files.
     
    .DESCRIPTION
        Converts building configuration files into building mod files.
        This command is used to read psd1-based configuration files for buildings and convert them into the format Stellaris expects.
        Generally, this command needs not be called directly and happens automatically during Build-PdxMod.
 
        For more details on how to define buildings via configuration file, see:
        https://github.com/FriedrichWeinmann/Paradox.Modding.Stellaris/blob/master/docs/content/buildings.md
     
    .PARAMETER Path
        Path to the file(s) to build.
     
    .PARAMETER ModRoot
        Root path of the mod you are building.
        Defaults to the parent folder of the parent folder of the first file specified in -Path.
     
    .EXAMPLE
        PS C:\> ConvertTo-PdsBuilding -Path "$PSScriptRoot\common\buildings\*.psd1"
 
        Builds all .psd1 files in the common\buildings subfolder under the path the current script is placed.
     
    .LINK
        https://github.com/FriedrichWeinmann/Paradox.Modding.Stellaris/blob/master/docs/content/buildings.md
    #>

    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        [Alias('FullName')]
        [PSFFile]
        $Path,

        [string]
        $ModRoot
    )
    begin {
        $commonProps = [ordered]@{
            Capital         = 'capital'
            CanBuild        = 'can_build'
            CanDemolish     = 'can_demolish'
            CanRuin         = 'can_be_ruined'
            CanDisable      = 'can_be_disabled'
            Position        = 'position_priority'
            BuildTime       = 'base_buildtime'
            EmpireLimit     = 'empire_limit'
            CanBeRuined     = 'can_be_ruined'
            Category        = 'category'
            Prerequisites   = 'prerequisites'
            UpgradeTo       = 'upgrades'
            Upgrades        = 'upgrades'
            Potential       = 'potential'
            Allow           = 'allow'
            PlanetModifier  = 'planet_modifier'
            CountryModifier = 'country_modifier'
        }

        $localeMap = @{
            Name        = '{0}'
            Description = '{0}_desc'
        }

        $typeMap = @{
            upgrades = 'array'
            prerequisites = 'array'
        }
    }
    process {
        foreach ($filePath in $Path) {
            if (-not $ModRoot) {
                $ModRoot = Split-Path -Path (Split-Path -Path (Split-Path -Path $filePath))
            }

            $strings = New-PdxLocalizedString
            $data = Import-PSFPowerShellDataFile -LiteralPath $filePath -Psd1Mode Unsafe
            $allBuildings = [ordered]@{}

            #region Build Edict Data
            foreach ($buildingName in $data.Buildings.Keys) {
                $buildingData = $data.Buildings.$buildingName

                $newBuilding = [ordered]@{}

                #region Cost & Upkeep
                $currentCost = $data.Core.Cost
                if ($buildingData.Cost) { $currentCost = $buildingData.Cost }
                $currentUpkeep = $data.Core.Upkeep
                if ($buildingData.Upkeep) { $currentUpkeep = $buildingData.Upkeep }

                if ($currentCost -or $currentUpkeep) {
                    $resourceData = [ordered]@{
                        category = 'planet_buildings'
                    }
                    if ($currentCost) {
                        if ($currentCost -is [int]) {
                            $resourceData['cost'] = @{ minerals = $currentCost }
                        }
                        else {
                            $resourceData['cost'] = $currentCost
                        }
                    }
                    if ($currentUpkeep) {
                        if ($currentUpkeep -is [int]) {
                            $resourceData['upkeep'] = @{ energy = $currentUpkeep }
                        }
                        else {
                            $resourceData['upkeep'] = $currentUpkeep
                        }
                    }
                    $newBuilding['resources'] = $resourceData
                }
                #endregion Cost & Upkeep

                $allBuildings[$buildingName] = New-PdxConfigEntry -Entry $buildingData -Name $buildingName -Defaults $data.Core -Common $commonProps -Output $newBuilding -Strings $strings -LocalizationProperties $localeMap -Ignore Cost, Upkeep -TypeMap $typeMap
            }
            #endregion Build Edict Data

            # Write File
            $sourceFile = Get-Item -LiteralPath $filePath
            $exportFile = Join-Path -Path $sourceFile.DirectoryName -ChildPath "$($sourceFile.BaseName).txt"
            $allBuildings | ConvertTo-PdxConfigFormat -TopLevel | Set-Content -Path $exportFile

            # Write Localization
            Export-PdxLocalizedString -Strings $strings -ModRoot $ModRoot -Name "buildings_$($sourceFile.BaseName)"
        }
    }
}

function ConvertTo-PdsEdict {
    <#
    .SYNOPSIS
        Converts edict configuration files into edict mod files.
     
    .DESCRIPTION
        Converts edict configuration files into edict mod files.
        This command is used to read psd1-based configuration files for edicts and convert them into the format Stellaris expects.
        Generally, this command needs not be called directly and happens automatically during Build-PdxMod.
 
        For more details on how to define edicts via configuration file, see:
        https://github.com/FriedrichWeinmann/Paradox.Modding.Stellaris/tree/master/docs/content/edicts.md
     
    .PARAMETER Path
        Path to the file(s) to build.
     
    .PARAMETER ModRoot
        Root path of the mod you are building.
        Defaults to the parent folder of the parent folder of the first file specified in -Path.
     
    .EXAMPLE
        PS C:\> ConvertTo-PdsEdict -Path "$PSScriptRoot\common\edicts\*.psd1"
 
        Builds all .psd1 files in the common\edicts subfolder under the path the current script is placed.
     
    .LINK
        https://github.com/FriedrichWeinmann/Paradox.Modding.Stellaris/tree/master/docs/content/edicts.md
    #>

    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        [Alias('FullName')]
        [PSFFile]
        $Path,

        [string]
        $ModRoot
    )
    begin {
        $commonProps = [ordered]@{
            Length = 'length'
            EdictCapUsage = 'edict_cap_usage'
            Potential = 'potential'
            Allow = 'allow'
            AIWeight = 'ai_weight'
            Modifier = 'modifier'
        }
    }
    process {
        foreach ($filePath in $Path) {
            if (-not $ModRoot) {
                $ModRoot = Split-Path -Path (Split-Path -Path (Split-Path -Path $filePath))
            }

            $strings = New-PdxLocalizedString
            $data = Import-PSFPowerShellDataFile -LiteralPath $filePath -Psd1Mode Unsafe
            $allEdicts = [ordered]@{}

            #region Build Edict Data
            foreach ($edictName in $data.Edicts.Keys) {
                $edictData = $data.Edicts.$edictName

                $newEdict = [ordered]@{}

                #region Cost
                $currentCost = $data.Core.Cost
                if ($edictData.Cost) { $currentCost = $edictData.Cost }
                if (-not $currentCost) { $currentCost = 0 }

                $costHash = @{ influence = $currentCost }
                if ($currentCost -isnot [int]) { $costhash = $currentCost }

                $newEdict['resources'] = [ordered]@{
                    category = 'edicts'
                    cost = $costHash
                }
                #endregion Cost

                $allEdicts[$edictName] = New-PdxConfigEntry -Entry $edictData -Name $edictName -Defaults $data.Core -Common $commonProps -Output $newEdict -Strings $strings -LocalizationProperties @{
                    Name = 'edict_{0}'
                    Description = 'edict_{0}_desc'
                } -Ignore Cost
            }
            #endregion Build Edict Data

            # Write File
            $sourceFile = Get-Item -LiteralPath $filePath
            $exportFile = Join-Path -Path $sourceFile.DirectoryName -ChildPath "$($sourceFile.BaseName).txt"
            $allEdicts | ConvertTo-PdxConfigFormat -TopLevel | Set-Content -Path $exportFile

            # Write Localization
            Export-PdxLocalizedString -Strings $strings -ModRoot $ModRoot -Name "edicts_$($sourceFile.BaseName)"
        }
    }
}

function Get-PdsGameDirectory {
    <#
    .SYNOPSIS
        Returns the root path to the Stellaris game installation.
     
    .DESCRIPTION
        Returns the root path to the Stellaris game installation.
        Uses steam to figure it out the path.
        Define the 'Paradox.Modding.Stellaris.Installpath' configuration setting (using Set-PSFConfig) to override (and disable) autodetection.
     
    .EXAMPLE
        PS C:\> Get-PdsGameDirectory
 
        returns the path to where the game is installed.
    #>

    [OutputType([string])]
    [CmdletBinding()]
    param ()
    process {
        # Configuration beats it all
        if (Get-PSFConfigValue -Fullname 'Paradox.Modding.Stellaris.Installpath') {
            return Get-PSFConfigValue -Fullname 'Paradox.Modding.Stellaris.Installpath'
        }

        # Once cached, do not resolve again.
        if ($script:_stellarisGamePath) { return $script:_stellarisGamePath }

        # Resolve using Steam configuration path.
        $steamLibraryCfgFile = "${env:ProgramFiles(x86)}\Steam\config\libraryfolders.vdf"
        $steamLibraries = Get-Content -Path $steamLibraryCfgFile | Where-Object { $_ -match '"path"' } | ForEach-Object {
            $_ -replace '^.+"path".+?"' -replace '".{0,}' -replace '\\\\', '\'
        }
        foreach ($path in $steamLibraries) {
            if (Test-Path -Path "$path\steamapps\common\Stellaris\stellaris.exe") {
                $script:_stellarisGamePath = "$path\steamapps\common\Stellaris"
                return "$path\steamapps\common\Stellaris"
            }
        }

        Stop-PSFFunction -Message "Stellaris installation path not found! Autodiscovery failed to detect it, use the following line to tell the module where to find the game:`nSet-PSFConfig -FullName 'Paradox.Modding.Stellaris.Installpath' -Value '<InsertPathhere>' -PassThru | Register-PSFConfig" -EnableException $true -Cmdlet $PSCmdlet
    }
}

Register-PdxBuildExtension -Name 'Stellaris.Edicts' -Tags 'stellaris','edicts' -Description 'Builds all edicts in a Stellaris mod' -Code {
    param ($Data)

    if (Test-Path "$($Data.Root)\common\edicts\*.psd1") {
        ConvertTo-PdsEdict -Path "$($Data.Root)\common\edicts\*.psd1"
    }
}
Register-PdxBuildExtension -Name 'Stellaris.Buildings' -Tags 'stellaris','buildings' -Description 'Builds all buildings in a Stellaris mod' -Code {
    param ($Data)

    if (Test-Path "$($Data.Root)\common\buildings\*.psd1") {
        ConvertTo-PdsBuilding -Path "$($Data.Root)\common\buildings\*.psd1"
    }
}

Set-PSFConfig -Fullname 'Paradox.Modding.Stellaris.Installpath' -Value '' -Validation string -Initialize -Description 'Path where the game was installed. Overrides auto-detection.'