# LAN party bootstrap for Windows: installs Fjord Launcher Unlocked (DRM-free # Prism fork), seeds a persistent offline account, drops in the pre-built # modpack instance, and launches straight into it on the LAN server. # # Hosted from Gitea (git.mivanchenko.de), not a local http.server — see HOSTING.md. # Participants run: irm https://git.mivanchenko.de/mivanchenko/mc-lan-party/raw/branch/main/install.ps1 | iex # ---- EDIT ME before hosting ---- $HostUrl = "https://git.mivanchenko.de/mivanchenko/mc-lan-party/raw/branch/main" # for this script + install.sh (small text files) $ModpackUrl = "https://minecraft.mivanchenko.de/modpack.zip" # served directly by Caddy (static/ mount), NOT Gitea — modpack.zip is well over Gitea's 50MB upload cap $InstanceName = "LANParty" $ServerAddr = "minecraft.mivanchenko.de:25565" # always-on homelab box, same address for prep and the actual party # --------------------------------- $ErrorActionPreference = "Stop" # fail loudly instead of printing an error and silently continuing $InstallDir = Join-Path $env:USERPROFILE "mc-lan-party" New-Item -ItemType Directory -Force -Path $InstallDir | Out-Null Set-Location $InstallDir Write-Host "==> Setting up in $InstallDir" $release = Invoke-RestMethod -Uri "https://api.github.com/repos/hero-persson/FjordLauncherUnlocked/releases/latest" $asset = $release.assets | Where-Object { $_.name -match "Windows-MSVC-Portable-.*\.zip$" } | Select-Object -First 1 if (-not $asset) { $asset = $release.assets | Where-Object { $_.name -match "Windows-MinGW-w64-Portable-.*\.zip$" } | Select-Object -First 1 } if (-not $asset) { throw "Could not find a Windows portable build in the latest Fjord Launcher Unlocked release." } Write-Host "==> Downloading $($asset.name)" Invoke-WebRequest -Uri $asset.browser_download_url -OutFile "FjordLauncher.zip" Expand-Archive -Path "FjordLauncher.zip" -DestinationPath "app" -Force $LauncherBin = Get-ChildItem -Path "app" -Filter "fjordlauncher.exe" -Recurse | Select-Object -First 1 -ExpandProperty FullName if (-not $LauncherBin) { throw "fjordlauncher.exe not found after extracting the portable build." } # ---- offline account: compute Mojang-style offline UUID so playerdata persists across launches ---- $Nick = Read-Host "Minecraft nickname [$env:USERNAME]" if ([string]::IsNullOrWhiteSpace($Nick)) { $Nick = $env:USERNAME } function Get-OfflineUuid([string]$name) { $md5 = [System.Security.Cryptography.MD5]::Create() $bytes = $md5.ComputeHash([System.Text.Encoding]::UTF8.GetBytes("OfflinePlayer:$name")) $bytes[6] = ($bytes[6] -band 0x0f) -bor 0x30 $bytes[8] = ($bytes[8] -band 0x3f) -bor 0x80 $hex = -join ($bytes | ForEach-Object { $_.ToString("x2") }) return "{0}-{1}-{2}-{3}-{4}" -f $hex.Substring(0,8), $hex.Substring(8,4), $hex.Substring(12,4), $hex.Substring(16,4), $hex.Substring(20,12) } $Uuid = Get-OfflineUuid $Nick $md5 = [System.Security.Cryptography.MD5]::Create() $clientTokenBytes = $md5.ComputeHash([System.Text.Encoding]::UTF8.GetBytes("ClientToken:$Nick")) $ClientToken = -join ($clientTokenBytes | ForEach-Object { $_.ToString("x2") }) $Iat = [int][double]::Parse((Get-Date -UFormat %s)) $accounts = @{ accounts = @( @{ active = $true type = "Offline" profile = @{ id = $Uuid; name = $Nick; capes = @(); skin = @{ id = ""; url = ""; variant = "" } } entitlement = @{ canPlayMinecraft = $true; ownsMinecraft = $true } ygg = @{ token = "0"; extra = @{ clientToken = $ClientToken; userName = $Nick }; iat = $Iat } } ) formatVersion = 3 } $accounts | ConvertTo-Json -Depth 6 | Set-Content -Path "accounts.json" -Encoding UTF8 Write-Host "==> Offline account '$Nick' ready (UUID $Uuid)" # ---- modpack instance ---- New-Item -ItemType Directory -Force -Path "instances" | Out-Null if (-not (Test-Path (Join-Path "instances" $InstanceName))) { Write-Host "==> Downloading modpack from $ModpackUrl" try { Invoke-WebRequest -Uri $ModpackUrl -OutFile "modpack.zip" Expand-Archive -Path "modpack.zip" -DestinationPath "instances" -Force } catch { Write-Host "==> FAILED to fetch/extract the modpack from $ModpackUrl" -ForegroundColor Red Write-Host " $($_.Exception.Message)" -ForegroundColor Red Write-Host " (Fjord Launcher itself installed fine at $InstallDir\app — this just means modpack.zip isn't being served yet.)" exit 1 } Write-Host "==> Modpack installed to instances\$InstanceName" } else { Write-Host "==> Instance already present, skipping download" } Write-Host "==> Launching into $InstanceName as $Nick, joining $ServerAddr" & $LauncherBin --dir $InstallDir --launch $InstanceName --profile $Nick --server $ServerAddr