bbba58d1dd
NeoForge's mod scanner rejected brassandsigil_tweaks-1.0.0.jar because PowerShell 5.1's [ZipFile]::CreateFromDirectory() writes Windows-native path separators into ZIP entry names on Windows. Entries came out as "META-INF\neoforge.mods.toml" instead of the spec-required forward-slash form, so the loader couldn't find the manifest and silently dropped the jar with "not a valid mod file". Build-Tweaks.ps1 now opens the archive in 'Create' mode and writes each file as an explicit ZipArchiveEntry whose name is built from the relative path with backslashes replaced by forward slashes. Verified the rebuilt jar lists "META-INF/neoforge.mods.toml" etc. Pack version 0.9.2 -> 0.9.3 so launchers cached at 0.9.2 see "pack changed" and re-sync the new tweak jar (their bytes differ; SHA-1 in the manifest will reflect that).
131 lines
4.9 KiB
PowerShell
131 lines
4.9 KiB
PowerShell
#requires -Version 5
|
|
<#
|
|
.SYNOPSIS
|
|
Builds every tweak source folder under ..\pack\tweaks\ into a data-only
|
|
mod jar and drops it into ..\pack\overrides\mods\.
|
|
|
|
.DESCRIPTION
|
|
Each subfolder of ..\pack\tweaks\ is treated as one self-contained
|
|
"data-only" NeoForge mod. Its modId, version, and display name come from
|
|
the folder's META-INF\neoforge.mods.toml. The script:
|
|
|
|
1. Reads modId + version from neoforge.mods.toml.
|
|
2. Zips the folder contents (data\, META-INF\, pack.mcmeta) into a jar
|
|
named "<modId>-<version>.jar".
|
|
3. Removes any older jars for the same modId from the output folder so
|
|
stale versions don't get bundled into the manifest.
|
|
|
|
Run this before Build-Pack.ps1, or let Build-Pack.ps1 invoke it for you.
|
|
|
|
.PARAMETER TweaksRoot
|
|
Folder containing tweak source subfolders. Defaults to ..\pack\tweaks\.
|
|
|
|
.PARAMETER OutputRoot
|
|
Where built jars go. Defaults to ..\pack\overrides\mods\. This path
|
|
becomes Build-Pack.ps1's -LocalPackSource (one level up).
|
|
#>
|
|
|
|
[CmdletBinding()]
|
|
param(
|
|
[string]$TweaksRoot = "",
|
|
[string]$OutputRoot = ""
|
|
)
|
|
|
|
$ErrorActionPreference = 'Stop'
|
|
$ProgressPreference = 'SilentlyContinue'
|
|
|
|
$here = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
if (-not $TweaksRoot) { $TweaksRoot = Join-Path $here '..\pack\tweaks' }
|
|
if (-not $OutputRoot) { $OutputRoot = Join-Path $here '..\pack\overrides\mods' }
|
|
|
|
if (-not (Test-Path $TweaksRoot)) {
|
|
Write-Host "No tweaks folder at $TweaksRoot -- nothing to build."
|
|
return
|
|
}
|
|
|
|
if (-not (Test-Path $OutputRoot)) {
|
|
New-Item -ItemType Directory -Path $OutputRoot -Force | Out-Null
|
|
}
|
|
|
|
# Read modId + version out of a neoforge.mods.toml. We do this with a tiny regex
|
|
# parser instead of a full TOML library because we only need two scalars and we
|
|
# control the file format. Lines like: modId = "foo" version = "1.2.3"
|
|
function Get-ModMeta {
|
|
param([string]$TomlPath)
|
|
if (-not (Test-Path $TomlPath)) {
|
|
throw "Missing $TomlPath -- every tweak folder needs META-INF\neoforge.mods.toml."
|
|
}
|
|
$content = Get-Content $TomlPath -Raw
|
|
|
|
$modIdMatch = [regex]::Match($content, '(?m)^\s*modId\s*=\s*"([^"]+)"')
|
|
$versionMatch = [regex]::Match($content, '(?m)^\s*version\s*=\s*"([^"]+)"')
|
|
|
|
if (-not $modIdMatch.Success) { throw "Could not parse modId from $TomlPath" }
|
|
if (-not $versionMatch.Success) { throw "Could not parse version from $TomlPath" }
|
|
|
|
return [pscustomobject]@{
|
|
ModId = $modIdMatch.Groups[1].Value
|
|
Version = $versionMatch.Groups[1].Value
|
|
}
|
|
}
|
|
|
|
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
|
|
|
$tweakDirs = Get-ChildItem -Path $TweaksRoot -Directory
|
|
|
|
if ($tweakDirs.Count -eq 0) {
|
|
Write-Host "No tweak folders found under $TweaksRoot."
|
|
return
|
|
}
|
|
|
|
Write-Host ""
|
|
Write-Host "Building tweak jars from $TweaksRoot"
|
|
Write-Host ""
|
|
|
|
foreach ($dir in $tweakDirs) {
|
|
$tomlPath = Join-Path $dir.FullName 'META-INF\neoforge.mods.toml'
|
|
$meta = Get-ModMeta -TomlPath $tomlPath
|
|
|
|
$jarName = "$($meta.ModId)-$($meta.Version).jar"
|
|
$jarPath = Join-Path $OutputRoot $jarName
|
|
|
|
# Wipe stale jars for this modId so old versions don't get bundled into
|
|
# the manifest alongside the new one.
|
|
Get-ChildItem -Path $OutputRoot -Filter "$($meta.ModId)-*.jar" -ErrorAction SilentlyContinue |
|
|
Where-Object { $_.Name -ne $jarName } |
|
|
ForEach-Object {
|
|
Write-Host (" removing stale: {0}" -f $_.Name)
|
|
Remove-Item $_.FullName -Force
|
|
}
|
|
|
|
if (Test-Path $jarPath) { Remove-Item $jarPath -Force }
|
|
|
|
# NB: PowerShell 5.1's [ZipFile]::CreateFromDirectory() writes Windows-
|
|
# native path separators (\) into ZIP entry names on Windows, producing
|
|
# entries like "META-INF\neoforge.mods.toml" instead of the spec-required
|
|
# "META-INF/neoforge.mods.toml". NeoForge's mod scanner then can't find
|
|
# the manifest and silently rejects the jar with "not a valid mod file".
|
|
# We build the archive manually so we control the entry name format.
|
|
# 'Create' string maps to ZipArchiveMode.Create -- PowerShell 5.1 doesn't
|
|
# auto-load the enum type, so the literal string form is more portable.
|
|
$zip = [System.IO.Compression.ZipFile]::Open($jarPath, 'Create')
|
|
try {
|
|
$sourceLen = $dir.FullName.Length
|
|
Get-ChildItem -Path $dir.FullName -Recurse -File | ForEach-Object {
|
|
$relPath = $_.FullName.Substring($sourceLen).TrimStart('\','/').Replace('\','/')
|
|
$entry = $zip.CreateEntry($relPath, [System.IO.Compression.CompressionLevel]::Optimal)
|
|
$entryStream = $entry.Open()
|
|
try {
|
|
$bytes = [System.IO.File]::ReadAllBytes($_.FullName)
|
|
$entryStream.Write($bytes, 0, $bytes.Length)
|
|
} finally { $entryStream.Dispose() }
|
|
}
|
|
} finally { $zip.Dispose() }
|
|
|
|
$size = (Get-Item $jarPath).Length
|
|
Write-Host (" built {0,-40} {1,8:N0} bytes" -f $jarName, $size)
|
|
}
|
|
|
|
Write-Host ""
|
|
Write-Host "Tweak jars are in: $OutputRoot"
|