mirror of
https://github.com/AutismDevelopment/Autism-Client.git
synced 2026-10-28 19:39:48 +00:00
908 lines
34 KiB
PowerShell
908 lines
34 KiB
PowerShell
param(
|
|
[ValidateSet("Menu", "Setup", "Scan", "Validate", "PublishApi", "Build", "BuildAll", "Clean")]
|
|
[string] $Action = "Menu",
|
|
|
|
[ValidateSet("minimal", "advanced")]
|
|
[string] $Template = "minimal",
|
|
|
|
[string] $ProjectPath,
|
|
[string] $OutputPath,
|
|
[string] $AddonId,
|
|
[string] $AddonName,
|
|
[string] $AddonVersion,
|
|
[string] $Package,
|
|
[string] $Author,
|
|
[string] $Description,
|
|
[string] $MavenGroup,
|
|
[string] $ArchiveName,
|
|
[switch] $Advanced,
|
|
[switch] $DebugStack,
|
|
[switch] $NoPublish,
|
|
[switch] $Yes,
|
|
[switch] $NonInteractive
|
|
)
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
|
|
$RepoRoot = Split-Path -Parent $PSScriptRoot
|
|
|
|
function Write-Info([string] $Message) {
|
|
Write-Host "[AUTISM] $Message" -ForegroundColor DarkGray
|
|
}
|
|
|
|
function Write-Ok([string] $Message) {
|
|
Write-Host "[OK] $Message" -ForegroundColor Green
|
|
}
|
|
|
|
function Write-Warn([string] $Message) {
|
|
Write-Host "[WARN] $Message" -ForegroundColor DarkYellow
|
|
}
|
|
|
|
function Write-Bad([string] $Message) {
|
|
Write-Host "[FAIL] $Message" -ForegroundColor White -BackgroundColor Red
|
|
}
|
|
|
|
function Write-PathLine([string] $Label, [string] $Path) {
|
|
Write-Host "${Label}:" -ForegroundColor DarkGray
|
|
Write-Host $Path -ForegroundColor White
|
|
}
|
|
|
|
function Write-FailureItem([string] $Message) {
|
|
if ($Message -match "^[A-Za-z]:[\\/]" -or $Message -match "^/" -or $Message -match "^[.]{1,2}[\\/]") {
|
|
Write-PathLine "Path" $Message
|
|
} else {
|
|
Write-Bad " - $Message"
|
|
}
|
|
}
|
|
|
|
function Resolve-FullPath([string] $Path) {
|
|
if ([string]::IsNullOrWhiteSpace($Path)) {
|
|
return $null
|
|
}
|
|
if ([System.IO.Path]::IsPathRooted($Path)) {
|
|
return [System.IO.Path]::GetFullPath($Path)
|
|
}
|
|
return [System.IO.Path]::GetFullPath((Join-Path $RepoRoot $Path))
|
|
}
|
|
|
|
function Test-ShippedTemplatePath([string] $Path) {
|
|
if ([string]::IsNullOrWhiteSpace($Path)) {
|
|
return $false
|
|
}
|
|
$full = [System.IO.Path]::GetFullPath($Path).TrimEnd("\", "/")
|
|
foreach ($templateName in @("minimal", "advanced")) {
|
|
$templatePath = [System.IO.Path]::GetFullPath((Join-Path $RepoRoot "addon-templates/$templateName")).TrimEnd("\", "/")
|
|
if ([string]::Equals($full, $templatePath, [System.StringComparison]::OrdinalIgnoreCase)) {
|
|
return $true
|
|
}
|
|
}
|
|
return $false
|
|
}
|
|
|
|
function ConvertTo-FolderName([string] $Name) {
|
|
if ([string]::IsNullOrWhiteSpace($Name)) {
|
|
return "MyAddon"
|
|
}
|
|
$parts = [regex]::Matches($Name, "[A-Za-z0-9]+") | ForEach-Object { $_.Value }
|
|
if (-not $parts -or $parts.Count -eq 0) {
|
|
return "MyAddon"
|
|
}
|
|
$folder = (($parts | ForEach-Object {
|
|
if ($_.Length -eq 1) {
|
|
$_.ToUpperInvariant()
|
|
} else {
|
|
$_.Substring(0, 1).ToUpperInvariant() + $_.Substring(1)
|
|
}
|
|
}) -join "")
|
|
if ($folder.Length -gt 48) {
|
|
$folder = $folder.Substring(0, 48)
|
|
}
|
|
return $folder
|
|
}
|
|
|
|
function ConvertTo-PackageSegment([string] $Value) {
|
|
$segment = $Value.ToLowerInvariant() -replace "[^a-z0-9]+", ""
|
|
if ([string]::IsNullOrWhiteSpace($segment)) {
|
|
$segment = "myaddon"
|
|
}
|
|
if ($segment[0] -notmatch "[a-z]") {
|
|
$segment = "addon$segment"
|
|
}
|
|
return $segment
|
|
}
|
|
|
|
function Get-DefaultAuthor {
|
|
if (-not [string]::IsNullOrWhiteSpace($env:USERNAME)) {
|
|
return $env:USERNAME
|
|
}
|
|
return "You"
|
|
}
|
|
|
|
function Get-DefaultAddonOutputPath([string] $TemplateName, [string] $Name) {
|
|
$baseName = if ([string]::IsNullOrWhiteSpace($Name)) {
|
|
if ($TemplateName -eq "advanced") { "MyAdvancedAddon" } else { "MyAddon" }
|
|
} else {
|
|
ConvertTo-FolderName $Name
|
|
}
|
|
return Resolve-FullPath (Join-Path ".." $baseName)
|
|
}
|
|
|
|
function Read-Value([string] $Prompt, [string] $Default, [scriptblock] $Validator) {
|
|
while ($true) {
|
|
$suffix = if ([string]::IsNullOrWhiteSpace($Default)) { "" } else { " [$Default]" }
|
|
$value = Read-Host "$Prompt$suffix"
|
|
if ([string]::IsNullOrWhiteSpace($value)) {
|
|
$value = $Default
|
|
}
|
|
if ($null -eq $Validator -or (& $Validator $value)) {
|
|
return $value
|
|
}
|
|
Write-Warn "Bad value. Fix it."
|
|
}
|
|
}
|
|
|
|
function Read-VersionValue([string] $Current) {
|
|
$base = if ([string]::IsNullOrWhiteSpace($Current)) { "1.0.0" } else { $Current }
|
|
$next = Step-Version $base
|
|
while ($true) {
|
|
$value = Read-Host "Version current $base, blank = $next"
|
|
if ([string]::IsNullOrWhiteSpace($value)) {
|
|
return $next
|
|
}
|
|
if (Test-Version $value) {
|
|
return $value
|
|
}
|
|
Write-Warn "Bad version. Fix it."
|
|
}
|
|
}
|
|
|
|
function Test-ModId([string] $Value) {
|
|
return $Value -match "^[a-z][a-z0-9_-]{1,63}$"
|
|
}
|
|
|
|
function Test-JavaPackage([string] $Value) {
|
|
return $Value -match "^[a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]*)+$"
|
|
}
|
|
|
|
function Test-Version([string] $Value) {
|
|
return $Value -match "^[0-9A-Za-z][0-9A-Za-z._+-]*$"
|
|
}
|
|
|
|
function Step-Version([string] $Version) {
|
|
if ([string]::IsNullOrWhiteSpace($Version)) {
|
|
return "1.0.0"
|
|
}
|
|
$match = [regex]::Match($Version, "^(.*?)(\d+)(\D*)$")
|
|
if (-not $match.Success) {
|
|
return "$Version.1"
|
|
}
|
|
$prefix = $match.Groups[1].Value
|
|
$digits = $match.Groups[2].Value
|
|
$suffix = $match.Groups[3].Value
|
|
$next = ([int64] $digits) + 1
|
|
$nextText = [string] $next
|
|
if ($digits.Length -gt 1 -and $nextText.Length -lt $digits.Length) {
|
|
$nextText = $nextText.PadLeft($digits.Length, "0")
|
|
}
|
|
return "$prefix$nextText$suffix"
|
|
}
|
|
|
|
function ConvertTo-ModId([string] $Name) {
|
|
$id = $Name.ToLowerInvariant() -replace "[^a-z0-9_-]+", "-"
|
|
$id = $id.Trim("-_")
|
|
if ([string]::IsNullOrWhiteSpace($id)) {
|
|
return "my-autism-addon"
|
|
}
|
|
if ($id[0] -notmatch "[a-z]") {
|
|
$id = "addon-$id"
|
|
}
|
|
if ($id.Length -gt 64) {
|
|
$id = $id.Substring(0, 64).Trim("-_")
|
|
}
|
|
return $id
|
|
}
|
|
|
|
function Get-TextFile([string] $Path) {
|
|
return Get-Content -LiteralPath $Path -Raw
|
|
}
|
|
|
|
function Set-TextFile([string] $Path, [string] $Text) {
|
|
$fullPath = if (Test-Path -LiteralPath $Path) {
|
|
(Resolve-Path -LiteralPath $Path).Path
|
|
} else {
|
|
[System.IO.Path]::GetFullPath($Path)
|
|
}
|
|
$encoding = New-Object System.Text.UTF8Encoding($false)
|
|
[System.IO.File]::WriteAllText($fullPath, $Text, $encoding)
|
|
}
|
|
|
|
function Get-JsonFile([string] $Path) {
|
|
return Get-Content -LiteralPath $Path -Raw | ConvertFrom-Json
|
|
}
|
|
|
|
function Save-JsonFile([string] $Path, $Json) {
|
|
$text = $Json | ConvertTo-Json -Depth 64
|
|
$text = $text.Replace("\u003c", "<").Replace("\u003e", ">").Replace("\u0026", "&")
|
|
Set-TextFile $Path ($text + [Environment]::NewLine)
|
|
}
|
|
|
|
function Get-TomlVersion([string] $Path, [string] $Key) {
|
|
$text = Get-TextFile $Path
|
|
$match = [regex]::Match($text, "(?m)^\s*$([regex]::Escape($Key))\s*=\s*`"([^`"]+)`"")
|
|
if ($match.Success) {
|
|
return $match.Groups[1].Value
|
|
}
|
|
return ""
|
|
}
|
|
|
|
function Set-TomlVersion([string] $Path, [string] $Key, [string] $Value) {
|
|
$text = Get-TextFile $Path
|
|
$pattern = "(?m)^(\s*$([regex]::Escape($Key))\s*=\s*)`"[^`"]*`""
|
|
if ($text -match $pattern) {
|
|
$text = [regex]::Replace($text, $pattern, "`${1}`"$Value`"")
|
|
} else {
|
|
$text += [Environment]::NewLine + "$Key = `"$Value`"" + [Environment]::NewLine
|
|
}
|
|
Set-TextFile $Path $text
|
|
}
|
|
|
|
function Set-PropertiesValue([string] $Path, [string] $Key, [string] $Value) {
|
|
$text = Get-TextFile $Path
|
|
$pattern = "(?m)^$([regex]::Escape($Key))=.*$"
|
|
if ($text -match $pattern) {
|
|
$text = [regex]::Replace($text, $pattern, "$Key=$Value")
|
|
} else {
|
|
$text += [Environment]::NewLine + "$Key=$Value" + [Environment]::NewLine
|
|
}
|
|
Set-TextFile $Path $text
|
|
}
|
|
|
|
function Set-RootProjectName([string] $Path, [string] $Name) {
|
|
$text = Get-TextFile $Path
|
|
$pattern = "(?m)^(rootProject\.name\s*=\s*)`"[^`"]*`""
|
|
if ($text -match $pattern) {
|
|
$text = [regex]::Replace($text, $pattern, "`${1}`"$Name`"")
|
|
} else {
|
|
$text += [Environment]::NewLine + "rootProject.name = `"$Name`"" + [Environment]::NewLine
|
|
}
|
|
Set-TextFile $Path $text
|
|
}
|
|
|
|
function Get-FirstJavaPackage([string] $Project) {
|
|
$entry = Join-Path $Project "src/main/resources/fabric.mod.json"
|
|
if (Test-Path -LiteralPath $entry -PathType Leaf) {
|
|
$json = Get-JsonFile $entry
|
|
$classes = @()
|
|
if ($json.entrypoints.client) { $classes += @($json.entrypoints.client) }
|
|
if ($json.entrypoints.autism) { $classes += @($json.entrypoints.autism) }
|
|
foreach ($class in $classes) {
|
|
if ($class -match "^(.+)\.[^.]+$") {
|
|
return $matches[1]
|
|
}
|
|
}
|
|
}
|
|
|
|
$java = Get-ChildItem -LiteralPath (Join-Path $Project "src/main/java") -Recurse -Filter *.java -ErrorAction SilentlyContinue | Select-Object -First 1
|
|
if ($java) {
|
|
$match = [regex]::Match((Get-TextFile $java.FullName), "(?m)^\s*package\s+([^;]+);")
|
|
if ($match.Success) {
|
|
return $match.Groups[1].Value.Trim()
|
|
}
|
|
}
|
|
return "com.example.addon"
|
|
}
|
|
|
|
function Get-ClassSimpleName([string] $ClassName, [string] $Fallback) {
|
|
if ($ClassName -match "\.([^.]+)$") {
|
|
return $matches[1]
|
|
}
|
|
return $Fallback
|
|
}
|
|
|
|
function Replace-InProjectFiles([string] $Project, [string] $Old, [string] $New) {
|
|
if ([string]::IsNullOrWhiteSpace($Old) -or $Old -eq $New) {
|
|
return
|
|
}
|
|
$extensions = @(".java", ".json", ".kts", ".toml", ".properties", ".md", ".yml", ".yaml")
|
|
$files = Get-ChildItem -LiteralPath $Project -Recurse -File -Force | Where-Object {
|
|
$_.FullName -notmatch "\\(build|\.gradle)\\" -and $extensions -contains $_.Extension
|
|
}
|
|
foreach ($file in $files) {
|
|
$text = Get-TextFile $file.FullName
|
|
if ($text.Contains($Old)) {
|
|
Set-TextFile $file.FullName ($text.Replace($Old, $New))
|
|
}
|
|
}
|
|
}
|
|
|
|
function Move-JavaPackage([string] $Project, [string] $OldPackage, [string] $NewPackage) {
|
|
if ($OldPackage -eq $NewPackage) {
|
|
return
|
|
}
|
|
$srcRoot = Join-Path $Project "src/main/java"
|
|
$oldPath = Join-Path $srcRoot ($OldPackage.Replace(".", [System.IO.Path]::DirectorySeparatorChar))
|
|
$newPath = Join-Path $srcRoot ($NewPackage.Replace(".", [System.IO.Path]::DirectorySeparatorChar))
|
|
if (-not (Test-Path -LiteralPath $oldPath -PathType Container)) {
|
|
return
|
|
}
|
|
if (Test-Path -LiteralPath $newPath) {
|
|
Write-Warn "Package path already exists. Not moving files."
|
|
Write-PathLine "Path" $newPath
|
|
return
|
|
}
|
|
|
|
New-Item -ItemType Directory -Force -Path (Split-Path -Parent $newPath) | Out-Null
|
|
Move-Item -LiteralPath $oldPath -Destination $newPath
|
|
|
|
$cursor = Split-Path -Parent $oldPath
|
|
while ($cursor -and $cursor.StartsWith($srcRoot) -and $cursor -ne $srcRoot) {
|
|
$children = Get-ChildItem -LiteralPath $cursor -Force
|
|
if ($children.Count -gt 0) {
|
|
break
|
|
}
|
|
$next = Split-Path -Parent $cursor
|
|
Remove-Item -LiteralPath $cursor
|
|
$cursor = $next
|
|
}
|
|
}
|
|
|
|
function Copy-AddonTemplate([string] $TemplateName, [string] $TargetPath) {
|
|
$source = Join-Path $RepoRoot "addon-templates/$TemplateName"
|
|
if (-not (Test-Path -LiteralPath $source -PathType Container)) {
|
|
Write-PathLine "Missing template" $source
|
|
throw "Template not found."
|
|
}
|
|
if (Test-Path -LiteralPath $TargetPath) {
|
|
Write-Warn "Output already exists. Editing it in place."
|
|
Write-PathLine "Path" $TargetPath
|
|
return
|
|
}
|
|
New-Item -ItemType Directory -Force -Path $TargetPath | Out-Null
|
|
$sourceFull = [System.IO.Path]::GetFullPath($source)
|
|
$targetFull = [System.IO.Path]::GetFullPath($TargetPath)
|
|
Get-ChildItem -LiteralPath $sourceFull -Recurse -Force | Where-Object {
|
|
$_.FullName -notmatch "\\(build|\.gradle)($|\\)"
|
|
} | ForEach-Object {
|
|
$relative = $_.FullName.Substring($sourceFull.Length).TrimStart("\", "/")
|
|
$destination = Join-Path $targetFull $relative
|
|
if ($_.PSIsContainer) {
|
|
New-Item -ItemType Directory -Force -Path $destination | Out-Null
|
|
} else {
|
|
New-Item -ItemType Directory -Force -Path (Split-Path -Parent $destination) | Out-Null
|
|
Copy-Item -LiteralPath $_.FullName -Destination $destination -Force
|
|
}
|
|
}
|
|
}
|
|
|
|
function Get-AddonProjectPath {
|
|
if (-not [string]::IsNullOrWhiteSpace($ProjectPath)) {
|
|
return Resolve-FullPath $ProjectPath
|
|
}
|
|
if (-not [string]::IsNullOrWhiteSpace($OutputPath)) {
|
|
$target = Resolve-FullPath $OutputPath
|
|
Copy-AddonTemplate $Template $target
|
|
return $target
|
|
}
|
|
return Join-Path $RepoRoot "addon-templates/$Template"
|
|
}
|
|
|
|
function Get-SetupProjectPath([string] $NameForOutput) {
|
|
if (-not [string]::IsNullOrWhiteSpace($ProjectPath)) {
|
|
$project = Resolve-FullPath $ProjectPath
|
|
if (Test-ShippedTemplatePath $project) {
|
|
throw "No. The shipped templates stay clean. Use -OutputPath to copy one, or pick a real addon folder."
|
|
}
|
|
return $project
|
|
}
|
|
if ([string]::IsNullOrWhiteSpace($OutputPath)) {
|
|
$OutputPath = Read-Value "Output folder" (Get-DefaultAddonOutputPath $Template $NameForOutput) { param($v) -not [string]::IsNullOrWhiteSpace($v) }
|
|
}
|
|
$target = Resolve-FullPath $OutputPath
|
|
if (Test-ShippedTemplatePath $target) {
|
|
throw "No. The shipped templates stay clean. Pick a different output folder."
|
|
}
|
|
Copy-AddonTemplate $Template $target
|
|
return $target
|
|
}
|
|
|
|
function Configure-Addon {
|
|
if ([string]::IsNullOrWhiteSpace($AddonName)) {
|
|
$defaultName = if ($Template -eq "advanced") { "My Advanced Addon" } else { "My Addon" }
|
|
$AddonName = Read-Value "Addon name" $defaultName { param($v) -not [string]::IsNullOrWhiteSpace($v) }
|
|
}
|
|
|
|
$project = Get-SetupProjectPath $AddonName
|
|
if (-not (Test-Path -LiteralPath $project -PathType Container)) {
|
|
Write-PathLine "Missing addon folder" $project
|
|
throw "Addon project not found."
|
|
}
|
|
|
|
$fabricPath = Join-Path $project "src/main/resources/fabric.mod.json"
|
|
$versionsPath = Join-Path $project "gradle/libs.versions.toml"
|
|
$propertiesPath = Join-Path $project "gradle.properties"
|
|
$settingsPath = Join-Path $project "settings.gradle.kts"
|
|
foreach ($required in @($fabricPath, $versionsPath, $propertiesPath, $settingsPath)) {
|
|
if (-not (Test-Path -LiteralPath $required -PathType Leaf)) {
|
|
Write-PathLine "Missing file" $required
|
|
throw "Missing required addon file."
|
|
}
|
|
}
|
|
|
|
$fabric = Get-JsonFile $fabricPath
|
|
$oldId = [string] $fabric.id
|
|
$oldName = [string] $fabric.name
|
|
$oldPackage = Get-FirstJavaPackage $project
|
|
$oldVersion = Get-TomlVersion $versionsPath "mod-version"
|
|
$oldClientClass = if ($fabric.entrypoints.client) { [string] @($fabric.entrypoints.client)[0] } else { "$oldPackage.Init" }
|
|
$oldAddonClass = if ($fabric.entrypoints.autism) { [string] @($fabric.entrypoints.autism)[0] } else { "$oldPackage.Addon" }
|
|
$originalMixinName = if ($fabric.mixins -and @($fabric.mixins).Count -gt 0) { [string] @($fabric.mixins)[0] } else { "" }
|
|
$clientSimple = Get-ClassSimpleName $oldClientClass "Init"
|
|
$addonSimple = Get-ClassSimpleName $oldAddonClass "Addon"
|
|
|
|
if ([string]::IsNullOrWhiteSpace($AddonId)) {
|
|
$suggestedId = if ($oldId -match "template") { ConvertTo-ModId $AddonName } else { $oldId }
|
|
if ($Advanced) {
|
|
$AddonId = Read-Value "Addon id" $suggestedId { param($v) Test-ModId $v }
|
|
} else {
|
|
$AddonId = $suggestedId
|
|
}
|
|
}
|
|
if ([string]::IsNullOrWhiteSpace($AddonVersion)) {
|
|
$suggestedVersion = if ([string]::IsNullOrWhiteSpace($oldVersion)) { "1.0.0" } else { $oldVersion }
|
|
$AddonVersion = Read-VersionValue $suggestedVersion
|
|
}
|
|
if ([string]::IsNullOrWhiteSpace($Package)) {
|
|
$suggestedPackage = "com.$(ConvertTo-PackageSegment $AddonId).addon"
|
|
if ($Advanced) {
|
|
$Package = Read-Value "Java package" $suggestedPackage { param($v) Test-JavaPackage $v }
|
|
} else {
|
|
$Package = $suggestedPackage
|
|
}
|
|
}
|
|
if ([string]::IsNullOrWhiteSpace($MavenGroup)) {
|
|
if ($Advanced) {
|
|
$MavenGroup = Read-Value "Maven group" $Package { param($v) Test-JavaPackage $v }
|
|
} else {
|
|
$MavenGroup = $Package
|
|
}
|
|
}
|
|
if ([string]::IsNullOrWhiteSpace($ArchiveName)) {
|
|
if ($Advanced) {
|
|
$ArchiveName = Read-Value "Jar/archive base name" $AddonId { param($v) Test-ModId $v }
|
|
} else {
|
|
$ArchiveName = $AddonId
|
|
}
|
|
}
|
|
if ([string]::IsNullOrWhiteSpace($Author)) {
|
|
$Author = Read-Value "Author" (Get-DefaultAuthor) { param($v) -not [string]::IsNullOrWhiteSpace($v) }
|
|
}
|
|
if ([string]::IsNullOrWhiteSpace($Description)) {
|
|
$suggestedDescription = "$AddonName addon for AUTISM Client."
|
|
if ($Advanced) {
|
|
$Description = Read-Value "Description" $suggestedDescription { param($v) -not [string]::IsNullOrWhiteSpace($v) }
|
|
} else {
|
|
$Description = $suggestedDescription
|
|
}
|
|
}
|
|
|
|
Replace-InProjectFiles $project $oldPackage $Package
|
|
Replace-InProjectFiles $project $oldId $AddonId
|
|
Move-JavaPackage $project $oldPackage $Package
|
|
|
|
$fabric = Get-JsonFile $fabricPath
|
|
$fabric.id = $AddonId
|
|
$fabric.name = $AddonName
|
|
$fabric.version = '${version}'
|
|
$fabric.description = $Description
|
|
$fabric.authors = @($Author)
|
|
if (-not $fabric.entrypoints) {
|
|
$fabric | Add-Member -MemberType NoteProperty -Name entrypoints -Value ([pscustomobject]@{})
|
|
}
|
|
$fabric.entrypoints.client = @("$Package.$clientSimple")
|
|
$fabric.entrypoints.autism = @("$Package.$addonSimple")
|
|
|
|
if ($fabric.mixins -and @($fabric.mixins).Count -gt 0) {
|
|
$oldMixinName = if ([string]::IsNullOrWhiteSpace($originalMixinName)) { [string] @($fabric.mixins)[0] } else { $originalMixinName }
|
|
$newMixinName = "$AddonId.mixins.json"
|
|
$resourceDir = Join-Path $project "src/main/resources"
|
|
$oldMixinPath = Join-Path $resourceDir $oldMixinName
|
|
$newMixinPath = Join-Path $resourceDir $newMixinName
|
|
if ((Test-Path -LiteralPath $oldMixinPath -PathType Leaf) -and $oldMixinPath -ne $newMixinPath) {
|
|
Move-Item -LiteralPath $oldMixinPath -Destination $newMixinPath -Force
|
|
}
|
|
if (Test-Path -LiteralPath $newMixinPath -PathType Leaf) {
|
|
$mixinJson = Get-JsonFile $newMixinPath
|
|
$mixinJson.package = "$Package.mixin"
|
|
Save-JsonFile $newMixinPath $mixinJson
|
|
}
|
|
$fabric.mixins = @($newMixinName)
|
|
}
|
|
|
|
Save-JsonFile $fabricPath $fabric
|
|
Set-TomlVersion $versionsPath "mod-version" $AddonVersion
|
|
Set-PropertiesValue $propertiesPath "maven_group" $MavenGroup
|
|
Set-PropertiesValue $propertiesPath "archives_base_name" $ArchiveName
|
|
Set-RootProjectName $settingsPath $AddonId
|
|
|
|
Write-Ok "Addon rewritten."
|
|
Write-PathLine "Addon folder" $project
|
|
Write-Host " id: $AddonId"
|
|
Write-Host " name: $AddonName"
|
|
Write-Host " version: $AddonVersion"
|
|
Write-Host " package: $Package"
|
|
Write-Host ""
|
|
Write-Host "Next:" -ForegroundColor Red
|
|
Write-Host ".\addon-templates\addon-toolkit.ps1 -Action Build -ProjectPath `"$project`"" -ForegroundColor White
|
|
Write-PathLine "Jar folder" (Join-Path $project "build\libs")
|
|
$script:LastConfiguredProject = $project
|
|
}
|
|
|
|
function Add-Failure([System.Collections.Generic.List[string]] $Failures, [string] $Message) {
|
|
$Failures.Add($Message) | Out-Null
|
|
}
|
|
|
|
function Add-Warning([System.Collections.Generic.List[string]] $Warnings, [string] $Message) {
|
|
$Warnings.Add($Message) | Out-Null
|
|
}
|
|
|
|
function Test-AddonProject([string] $Project, [switch] $AllowTemplateNames) {
|
|
$failures = New-Object System.Collections.Generic.List[string]
|
|
$warnings = New-Object System.Collections.Generic.List[string]
|
|
|
|
if (-not (Test-Path -LiteralPath $Project -PathType Container)) {
|
|
Add-Failure $failures "Project folder does not exist."
|
|
Add-Failure $failures $Project
|
|
return [pscustomobject]@{ Failures = $failures; Warnings = $warnings }
|
|
}
|
|
|
|
$required = @(
|
|
"build.gradle.kts",
|
|
"settings.gradle.kts",
|
|
"gradle.properties",
|
|
"gradle/libs.versions.toml",
|
|
"gradlew.bat",
|
|
"src/main/resources/fabric.mod.json"
|
|
)
|
|
foreach ($item in $required) {
|
|
if (-not (Test-Path -LiteralPath (Join-Path $Project $item) -PathType Leaf)) {
|
|
Add-Failure $failures "Missing $item"
|
|
}
|
|
}
|
|
|
|
$fabricPath = Join-Path $Project "src/main/resources/fabric.mod.json"
|
|
if (Test-Path -LiteralPath $fabricPath -PathType Leaf) {
|
|
try {
|
|
$fabric = Get-JsonFile $fabricPath
|
|
if (-not (Test-ModId ([string] $fabric.id))) {
|
|
Add-Failure $failures "fabric.mod.json id is invalid: $($fabric.id)"
|
|
}
|
|
if ([string]::IsNullOrWhiteSpace([string] $fabric.name)) {
|
|
Add-Failure $failures "fabric.mod.json name is empty."
|
|
}
|
|
if (-not $fabric.entrypoints.autism) {
|
|
Add-Failure $failures "Missing autism entrypoint in fabric.mod.json."
|
|
} else {
|
|
foreach ($entry in @($fabric.entrypoints.autism)) {
|
|
$path = Join-Path $Project ("src/main/java/" + ([string] $entry).Replace(".", "/") + ".java")
|
|
if (-not (Test-Path -LiteralPath $path -PathType Leaf)) {
|
|
Add-Failure $failures "Autism entrypoint class file is missing: $entry"
|
|
}
|
|
}
|
|
}
|
|
if (-not $fabric.depends.autism) {
|
|
Add-Failure $failures "fabric.mod.json must depend on autism."
|
|
}
|
|
if (-not $AllowTemplateNames) {
|
|
if ([string] $fabric.id -match "template|example") {
|
|
Add-Warning $warnings "Addon id still looks like a template/example."
|
|
}
|
|
if ([string] $fabric.name -match "Template|Example") {
|
|
Add-Warning $warnings "Addon name still looks like a template/example."
|
|
}
|
|
if (@($fabric.authors) -contains "You") {
|
|
Add-Warning $warnings "Author is still 'You'."
|
|
}
|
|
}
|
|
} catch {
|
|
Add-Failure $failures "fabric.mod.json is not valid JSON: $($_.Exception.Message)"
|
|
}
|
|
}
|
|
|
|
$versionsPath = Join-Path $Project "gradle/libs.versions.toml"
|
|
if (Test-Path -LiteralPath $versionsPath -PathType Leaf) {
|
|
$addonVersion = Get-TomlVersion $versionsPath "mod-version"
|
|
$hostVersion = Get-TomlVersion $versionsPath "autism"
|
|
if (-not (Test-Version $addonVersion)) {
|
|
Add-Failure $failures "Addon mod-version is missing or invalid."
|
|
}
|
|
if ([string]::IsNullOrWhiteSpace($hostVersion)) {
|
|
Add-Failure $failures "AUTISM dependency version is missing from gradle/libs.versions.toml."
|
|
}
|
|
}
|
|
|
|
if (Test-Path -LiteralPath (Join-Path $Project ".gradle")) {
|
|
Add-Warning $warnings ".gradle cache exists locally. Ignored; do not upload it."
|
|
}
|
|
if (Test-Path -LiteralPath (Join-Path $Project "build")) {
|
|
Add-Warning $warnings "build output exists locally. Ignored; do not upload it."
|
|
}
|
|
if (Test-Path -LiteralPath (Join-Path $Project ".github")) {
|
|
Add-Warning $warnings ".github exists inside this addon project. Fine for a copied template, but it is not root repo CI unless you move it."
|
|
}
|
|
|
|
$files = Get-ChildItem -LiteralPath $Project -Recurse -File -Force | Where-Object {
|
|
$_.FullName -notmatch "\\(build|\.gradle)\\" -and
|
|
$_.Extension -in @(".java", ".json", ".md", ".kts", ".toml", ".properties", ".yml", ".yaml")
|
|
}
|
|
$templateLeftovers = @(
|
|
"autism-minimal-addon-template",
|
|
"autism-advanced-addon-template",
|
|
"AUTISM Minimal Addon Template",
|
|
"AUTISM Advanced Addon Template"
|
|
)
|
|
foreach ($file in $files) {
|
|
$text = Get-TextFile $file.FullName
|
|
if ($text -match "[\u00C2\u00C3\u00E2]") {
|
|
Add-Warning $warnings "Mojibake-looking text in $($file.FullName)"
|
|
}
|
|
if (-not $AllowTemplateNames) {
|
|
foreach ($leftover in $templateLeftovers) {
|
|
if ($text.Contains($leftover)) {
|
|
Add-Warning $warnings "Template leftover '$leftover' in $($file.FullName)"
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return [pscustomobject]@{ Failures = $failures; Warnings = $warnings }
|
|
}
|
|
|
|
function Scan-Addon {
|
|
$project = Get-AddonProjectPath
|
|
$result = Test-AddonProject $project
|
|
Write-Info "Scanned addon project."
|
|
Write-PathLine "Addon folder" $project
|
|
foreach ($warning in $result.Warnings) {
|
|
Write-Warn "Heads up: $warning"
|
|
}
|
|
if ($result.Failures.Count -gt 0) {
|
|
Write-Bad "Scan found broken stuff:"
|
|
foreach ($failure in $result.Failures) {
|
|
Write-FailureItem $failure
|
|
}
|
|
throw "Scan failed."
|
|
}
|
|
Write-Ok "Scan clean."
|
|
}
|
|
|
|
function Validate-AddonSystem {
|
|
$failures = New-Object System.Collections.Generic.List[string]
|
|
$warnings = New-Object System.Collections.Generic.List[string]
|
|
|
|
$rootRequired = @(
|
|
"src/main/java/autismclient/addons/AddonManager.java",
|
|
"src/main/java/autismclient/api/AutismAddon.java",
|
|
"src/main/java/autismclient/api/SimpleAddon.java",
|
|
"src/main/java/autismclient/api/AutismAddons.java",
|
|
"src/main/java/autismclient/api/ApiVersion.java",
|
|
"src/main/java/autismclient/api/module/SimpleModule.java",
|
|
"src/main/java/autismclient/api/macro/SimpleAction.java",
|
|
"src/main/java/autismclient/api/macro/SimpleCondition.java",
|
|
"src/main/java/autismclient/api/macro/MacroActionRegistry.java",
|
|
"src/main/java/autismclient/api/macro/MacroPresetRegistry.java",
|
|
"src/main/java/autismclient/api/hud/HudElements.java",
|
|
"src/main/java/autismclient/api/event/AddonEvents.java",
|
|
"src/main/java/autismclient/gui/screen/AutismAddonsScreen.java",
|
|
"src/main/java/autismclient/util/macro/MissingAddonAction.java",
|
|
"addon-templates/README.md",
|
|
"addon-templates/addon-toolkit.ps1"
|
|
)
|
|
foreach ($file in $rootRequired) {
|
|
if (-not (Test-Path -LiteralPath (Join-Path $RepoRoot $file) -PathType Leaf)) {
|
|
Add-Failure $failures "Missing $file"
|
|
}
|
|
}
|
|
|
|
$gitignore = Join-Path $RepoRoot ".gitignore"
|
|
if (Test-Path -LiteralPath $gitignore -PathType Leaf) {
|
|
$ignoreText = Get-TextFile $gitignore
|
|
foreach ($pattern in @("!/src/", "!/addon-templates/", "!/addon-templates/**", "/addon-templates/**/build/", "/addon-templates/**/.gradle/", "/mc-src*/")) {
|
|
if (-not $ignoreText.Contains($pattern)) {
|
|
Add-Failure $failures ".gitignore is missing $pattern"
|
|
}
|
|
}
|
|
} else {
|
|
Add-Failure $failures "Missing .gitignore"
|
|
}
|
|
|
|
$mainVersion = Get-TomlVersion (Join-Path $RepoRoot "gradle/libs.versions.toml") "mod-version"
|
|
foreach ($templateName in @("minimal", "advanced")) {
|
|
$project = Join-Path $RepoRoot "addon-templates/$templateName"
|
|
$result = Test-AddonProject $project -AllowTemplateNames
|
|
foreach ($failure in $result.Failures) {
|
|
Add-Failure $failures "$templateName template: $failure"
|
|
}
|
|
foreach ($warning in $result.Warnings) {
|
|
Add-Warning $warnings "$templateName template: $warning"
|
|
}
|
|
$targetVersion = Get-TomlVersion (Join-Path $project "gradle/libs.versions.toml") "autism"
|
|
if ($mainVersion -and $targetVersion -and $mainVersion -ne $targetVersion) {
|
|
Add-Failure $failures "$templateName template targets AUTISM $targetVersion, main client is $mainVersion."
|
|
}
|
|
}
|
|
|
|
foreach ($warning in $warnings) {
|
|
Write-Warn "Heads up: $warning"
|
|
}
|
|
if ($failures.Count -gt 0) {
|
|
Write-Bad "Addon system is broken:"
|
|
foreach ($failure in $failures) {
|
|
Write-FailureItem $failure
|
|
}
|
|
throw "Addon system validation failed."
|
|
}
|
|
Write-Ok "Addon system clean."
|
|
}
|
|
|
|
function Invoke-Gradle([string] $Project, [string[]] $GradleArgs) {
|
|
$gradlew = Join-Path $Project "gradlew.bat"
|
|
if (-not (Test-Path -LiteralPath $gradlew -PathType Leaf)) {
|
|
Write-PathLine "Missing Gradle wrapper" $gradlew
|
|
throw "Missing Gradle wrapper."
|
|
}
|
|
Push-Location $Project
|
|
try {
|
|
& $gradlew @GradleArgs
|
|
if ($LASTEXITCODE -ne 0) {
|
|
Write-PathLine "Gradle project" $Project
|
|
throw "Gradle failed with exit code $LASTEXITCODE."
|
|
}
|
|
} finally {
|
|
Pop-Location
|
|
}
|
|
}
|
|
|
|
function Publish-Api {
|
|
Write-Info "Publishing client API to Maven Local."
|
|
Invoke-Gradle $RepoRoot @("publishToMavenLocal", "--no-daemon")
|
|
Write-Ok "Client API published."
|
|
}
|
|
|
|
function Build-Addon {
|
|
$project = Get-AddonProjectPath
|
|
if (-not (Test-Path -LiteralPath $project -PathType Container)) {
|
|
Write-PathLine "Addon folder" $project
|
|
throw "Wrong addon folder."
|
|
}
|
|
$gradlew = [System.IO.Path]::Combine($project, "gradlew.bat")
|
|
if (-not (Test-Path -LiteralPath $gradlew -PathType Leaf)) {
|
|
Write-PathLine "Addon folder" $project
|
|
throw "No Gradle wrapper there. Wrong addon folder."
|
|
}
|
|
if (-not $NoPublish) {
|
|
Publish-Api
|
|
}
|
|
Write-Info "Building addon."
|
|
Write-PathLine "Addon folder" $project
|
|
Invoke-Gradle $project @("build", "--no-daemon")
|
|
Write-Ok "Addon built."
|
|
Write-PathLine "Addon folder" $project
|
|
Write-PathLine "Jar folder" (Join-Path $project "build\libs")
|
|
}
|
|
|
|
function Build-AllTemplates {
|
|
if (-not $NoPublish) {
|
|
Publish-Api
|
|
}
|
|
foreach ($templateName in @("minimal", "advanced")) {
|
|
$project = Join-Path $RepoRoot "addon-templates/$templateName"
|
|
Write-Info "Building $templateName template."
|
|
Invoke-Gradle $project @("build", "--no-daemon")
|
|
Write-Ok "$templateName template built."
|
|
}
|
|
}
|
|
|
|
function Clean-Addon {
|
|
$project = Get-AddonProjectPath
|
|
foreach ($folder in @(".gradle", "build")) {
|
|
$path = Join-Path $project $folder
|
|
if (Test-Path -LiteralPath $path) {
|
|
if ($Yes -or ((Read-Host "Remove $path ? Type YES") -eq "YES")) {
|
|
Remove-Item -LiteralPath $path -Recurse -Force
|
|
Write-Ok "Deleted local build junk."
|
|
Write-PathLine "Path" $path
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function Invoke-MenuChoice([scriptblock] $Body) {
|
|
try {
|
|
& $Body
|
|
} catch {
|
|
Write-Bad $_.Exception.Message
|
|
if ($DebugStack -and $_.ScriptStackTrace) {
|
|
Write-Warn $_.ScriptStackTrace
|
|
}
|
|
[void] (Read-Host "Press Enter. The error stays here until you do")
|
|
}
|
|
}
|
|
|
|
function Show-Menu {
|
|
$script:LastAddonPath = ""
|
|
while ($true) {
|
|
Write-Host ""
|
|
Write-Host "AUTISM ADDON KIT" -ForegroundColor Red
|
|
Write-Host "1. New addon"
|
|
Write-Host "2. Build addon"
|
|
Write-Host "3. Scan addon"
|
|
Write-Host "4. Test shipped templates"
|
|
Write-Host "5. Publish client API"
|
|
Write-Host "6. Delete local build junk"
|
|
Write-Host "0. Leave"
|
|
$choice = Read-Host ">"
|
|
switch ($choice) {
|
|
"1" {
|
|
Invoke-MenuChoice {
|
|
$script:Template = Read-Value "Template minimal/advanced" $Template { param($v) $v -in @("minimal", "advanced") }
|
|
$script:ProjectPath = ""
|
|
$script:OutputPath = ""
|
|
Configure-Addon
|
|
$script:LastAddonPath = $script:LastConfiguredProject
|
|
}
|
|
}
|
|
"2" {
|
|
Invoke-MenuChoice {
|
|
$defaultPath = if ([string]::IsNullOrWhiteSpace($script:LastAddonPath)) { Get-DefaultAddonOutputPath $Template "" } else { $script:LastAddonPath }
|
|
$script:ProjectPath = Read-Value "Addon folder" $defaultPath { param($v) -not [string]::IsNullOrWhiteSpace($v) }
|
|
Build-Addon
|
|
}
|
|
}
|
|
"3" {
|
|
Invoke-MenuChoice {
|
|
$defaultPath = if ([string]::IsNullOrWhiteSpace($script:LastAddonPath)) { Get-DefaultAddonOutputPath $Template "" } else { $script:LastAddonPath }
|
|
$script:ProjectPath = Read-Value "Addon folder" $defaultPath { param($v) -not [string]::IsNullOrWhiteSpace($v) }
|
|
Scan-Addon
|
|
}
|
|
}
|
|
"4" { Invoke-MenuChoice { Validate-AddonSystem; Build-AllTemplates } }
|
|
"5" { Invoke-MenuChoice { Publish-Api } }
|
|
"6" {
|
|
Invoke-MenuChoice {
|
|
$defaultPath = if ([string]::IsNullOrWhiteSpace($script:LastAddonPath)) { Get-DefaultAddonOutputPath $Template "" } else { $script:LastAddonPath }
|
|
$script:ProjectPath = Read-Value "Addon folder" $defaultPath { param($v) -not [string]::IsNullOrWhiteSpace($v) }
|
|
Clean-Addon
|
|
}
|
|
}
|
|
"0" { return }
|
|
default { Write-Warn "Bad choice." }
|
|
}
|
|
}
|
|
}
|
|
|
|
function Invoke-RequestedAction {
|
|
switch ($Action) {
|
|
"Menu" { Show-Menu }
|
|
"Setup" { Configure-Addon }
|
|
"Scan" { Scan-Addon }
|
|
"Validate" { Validate-AddonSystem }
|
|
"PublishApi" { Publish-Api }
|
|
"Build" { Build-Addon }
|
|
"BuildAll" { Build-AllTemplates }
|
|
"Clean" { Clean-Addon }
|
|
}
|
|
}
|
|
|
|
try {
|
|
Invoke-RequestedAction
|
|
} catch {
|
|
Write-Bad $_.Exception.Message
|
|
if ($DebugStack -and $_.ScriptStackTrace) {
|
|
Write-Warn $_.ScriptStackTrace
|
|
}
|
|
if ($Action -eq "Menu" -or (-not $NonInteractive -and -not $env:CI)) {
|
|
[void] (Read-Host "Press Enter. The error stays here until you do")
|
|
}
|
|
exit 1
|
|
}
|