valheim-oz-dsm 1.4.3 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.js CHANGED
@@ -1690,7 +1690,7 @@ function parseValue(value) {
1690
1690
  }
1691
1691
 
1692
1692
  // src/cli/commands/doctor.ts
1693
- import fs4 from "fs/promises";
1693
+ import fs3 from "fs/promises";
1694
1694
  import net from "net";
1695
1695
  import path4 from "path";
1696
1696
  import steamcmd4 from "@caleb-collar/steamcmd";
@@ -1810,9 +1810,87 @@ async function isValheimInstalled() {
1810
1810
  return false;
1811
1811
  }
1812
1812
  }
1813
+ function getRequiredValheimFiles() {
1814
+ const platform = process.platform;
1815
+ if (platform === "win32") {
1816
+ return [
1817
+ "valheim_server.exe",
1818
+ "valheim_server_Data",
1819
+ "UnityPlayer.dll",
1820
+ "MonoBleedingEdge",
1821
+ "steam_appid.txt"
1822
+ ];
1823
+ }
1824
+ return [
1825
+ "valheim_server.x86_64",
1826
+ "valheim_server_Data",
1827
+ "UnityPlayer.so",
1828
+ "steam_appid.txt"
1829
+ ];
1830
+ }
1831
+ async function verifyValheimInstallation() {
1832
+ const { valheimDir } = getSteamPaths();
1833
+ const requiredFiles = getRequiredValheimFiles();
1834
+ const missingFiles = [];
1835
+ const foundFiles = [];
1836
+ try {
1837
+ const dirStat = await fs2.stat(valheimDir);
1838
+ if (!dirStat.isDirectory()) {
1839
+ return {
1840
+ valid: false,
1841
+ message: "Valheim installation path exists but is not a directory",
1842
+ missingFiles: requiredFiles,
1843
+ foundFiles: [],
1844
+ installPath: valheimDir
1845
+ };
1846
+ }
1847
+ } catch {
1848
+ return {
1849
+ valid: false,
1850
+ message: "Valheim dedicated server is not installed",
1851
+ missingFiles: requiredFiles,
1852
+ foundFiles: [],
1853
+ installPath: valheimDir
1854
+ };
1855
+ }
1856
+ for (const file of requiredFiles) {
1857
+ const filePath = path3.join(valheimDir, file);
1858
+ try {
1859
+ await fs2.stat(filePath);
1860
+ foundFiles.push(file);
1861
+ } catch {
1862
+ missingFiles.push(file);
1863
+ }
1864
+ }
1865
+ if (missingFiles.length === 0) {
1866
+ return {
1867
+ valid: true,
1868
+ message: "Valheim installation verified successfully",
1869
+ missingFiles: [],
1870
+ foundFiles,
1871
+ installPath: valheimDir
1872
+ };
1873
+ }
1874
+ const executableFile = process.platform === "win32" ? "valheim_server.exe" : "valheim_server.x86_64";
1875
+ if (missingFiles.includes(executableFile)) {
1876
+ return {
1877
+ valid: false,
1878
+ message: `Valheim server executable not found. Missing: ${missingFiles.join(", ")}`,
1879
+ missingFiles,
1880
+ foundFiles,
1881
+ installPath: valheimDir
1882
+ };
1883
+ }
1884
+ return {
1885
+ valid: false,
1886
+ message: `Valheim installation incomplete. Missing: ${missingFiles.join(", ")}`,
1887
+ missingFiles,
1888
+ foundFiles,
1889
+ installPath: valheimDir
1890
+ };
1891
+ }
1813
1892
 
1814
1893
  // src/steamcmd/updater.ts
1815
- import fs3 from "fs/promises";
1816
1894
  import steamcmd3 from "@caleb-collar/steamcmd";
1817
1895
  var VALHEIM_APP_ID = 896660;
1818
1896
  function mapPhaseToStage2(phase) {
@@ -1829,7 +1907,6 @@ function mapPhaseToStage2(phase) {
1829
1907
  }
1830
1908
  }
1831
1909
  async function installValheim(onProgress) {
1832
- const { steamcmdDir } = getSteamPaths();
1833
1910
  const report = (status) => {
1834
1911
  onProgress?.(status);
1835
1912
  };
@@ -1842,10 +1919,6 @@ async function installValheim(onProgress) {
1842
1919
  });
1843
1920
  throw new Error("SteamCMD is not installed");
1844
1921
  }
1845
- try {
1846
- await fs3.mkdir(steamcmdDir, { recursive: true });
1847
- } catch {
1848
- }
1849
1922
  report({
1850
1923
  stage: "downloading",
1851
1924
  progress: 0,
@@ -1854,7 +1927,6 @@ async function installValheim(onProgress) {
1854
1927
  try {
1855
1928
  await steamcmd3.install({
1856
1929
  applicationId: VALHEIM_APP_ID,
1857
- path: steamcmdDir,
1858
1930
  onProgress: (p) => {
1859
1931
  const stage = mapPhaseToStage2(p.phase);
1860
1932
  const progress = p.percent ?? 0;
@@ -1935,7 +2007,7 @@ async function getInstalledVersion() {
1935
2007
  // src/cli/commands/doctor.ts
1936
2008
  async function exists(filePath) {
1937
2009
  try {
1938
- await fs4.access(filePath);
2010
+ await fs3.access(filePath);
1939
2011
  return true;
1940
2012
  } catch {
1941
2013
  return false;
@@ -2083,9 +2155,9 @@ async function checkPermissions() {
2083
2155
  const steamCmdDir = info2.directory;
2084
2156
  const testFile = path4.join(steamCmdDir, ".oz-test-write");
2085
2157
  try {
2086
- await fs4.mkdir(steamCmdDir, { recursive: true });
2087
- await fs4.writeFile(testFile, "test");
2088
- await fs4.unlink(testFile);
2158
+ await fs3.mkdir(steamCmdDir, { recursive: true });
2159
+ await fs3.writeFile(testFile, "test");
2160
+ await fs3.unlink(testFile);
2089
2161
  return {
2090
2162
  name: "Directory Permissions",
2091
2163
  status: "pass",
@@ -2196,7 +2268,7 @@ Summary: ${passed} passed, ${warnings} warnings, ${failed} failed
2196
2268
  }
2197
2269
 
2198
2270
  // src/cli/commands/install.ts
2199
- import * as fs5 from "fs/promises";
2271
+ import * as fs4 from "fs/promises";
2200
2272
  async function installCommand(args) {
2201
2273
  const steamInstalled = await isSteamCmdInstalled();
2202
2274
  const valheimInstalled = await isValheimInstalled();
@@ -2259,7 +2331,7 @@ async function validateInstallation(steamInstalled, valheimInstalled, paths) {
2259
2331
  console.log(" \u2713 Installed");
2260
2332
  console.log(` Path: ${paths.steamcmd}`);
2261
2333
  try {
2262
- const stat3 = await fs5.stat(paths.steamcmd);
2334
+ const stat3 = await fs4.stat(paths.steamcmd);
2263
2335
  if (stat3.isFile()) {
2264
2336
  console.log(" \u2713 Executable found");
2265
2337
  }
@@ -2278,7 +2350,7 @@ async function validateInstallation(steamInstalled, valheimInstalled, paths) {
2278
2350
  console.log(` Path: ${paths.valheimDir}`);
2279
2351
  const exePath = `${paths.valheimDir}/${paths.executable}`;
2280
2352
  try {
2281
- const stat3 = await fs5.stat(exePath);
2353
+ const stat3 = await fs4.stat(exePath);
2282
2354
  if (stat3.isFile()) {
2283
2355
  console.log(" \u2713 Executable found");
2284
2356
  }
@@ -2493,7 +2565,7 @@ async function interactiveRcon(args) {
2493
2565
  }
2494
2566
 
2495
2567
  // src/server/commands.ts
2496
- import * as fs6 from "fs/promises";
2568
+ import * as fs5 from "fs/promises";
2497
2569
  import { dirname, join } from "path";
2498
2570
 
2499
2571
  // src/server/logs.ts
@@ -2544,7 +2616,7 @@ function parseEvent(line) {
2544
2616
  }
2545
2617
 
2546
2618
  // src/server/pidfile.ts
2547
- import fs7 from "fs/promises";
2619
+ import fs6 from "fs/promises";
2548
2620
  import path5 from "path";
2549
2621
  function getPidFilePath() {
2550
2622
  return path5.join(getConfigDir(), "oz-valheim", "server.pid");
@@ -2552,13 +2624,13 @@ function getPidFilePath() {
2552
2624
  async function writePidFile(data) {
2553
2625
  const pidPath = getPidFilePath();
2554
2626
  const dir = path5.dirname(pidPath);
2555
- await fs7.mkdir(dir, { recursive: true });
2556
- await fs7.writeFile(pidPath, JSON.stringify(data, null, 2), "utf-8");
2627
+ await fs6.mkdir(dir, { recursive: true });
2628
+ await fs6.writeFile(pidPath, JSON.stringify(data, null, 2), "utf-8");
2557
2629
  }
2558
2630
  async function readPidFile() {
2559
2631
  const pidPath = getPidFilePath();
2560
2632
  try {
2561
- const content = await fs7.readFile(pidPath, "utf-8");
2633
+ const content = await fs6.readFile(pidPath, "utf-8");
2562
2634
  return JSON.parse(content);
2563
2635
  } catch {
2564
2636
  return null;
@@ -2567,7 +2639,7 @@ async function readPidFile() {
2567
2639
  async function removePidFile() {
2568
2640
  const pidPath = getPidFilePath();
2569
2641
  try {
2570
- await fs7.unlink(pidPath);
2642
+ await fs6.unlink(pidPath);
2571
2643
  } catch {
2572
2644
  }
2573
2645
  }
@@ -3200,29 +3272,29 @@ Found running server:`);
3200
3272
  }
3201
3273
 
3202
3274
  // src/cli/commands/worlds.ts
3203
- import * as fs10 from "fs/promises";
3275
+ import * as fs9 from "fs/promises";
3204
3276
 
3205
3277
  // src/valheim/lists.ts
3206
- import fs8 from "fs/promises";
3278
+ import fs7 from "fs/promises";
3207
3279
  import path6 from "path";
3208
3280
 
3209
3281
  // src/valheim/worlds.ts
3210
- import fs9 from "fs/promises";
3282
+ import fs8 from "fs/promises";
3211
3283
  import path7 from "path";
3212
3284
  import process3 from "process";
3213
3285
  async function exists2(filePath) {
3214
3286
  try {
3215
- await fs9.access(filePath);
3287
+ await fs8.access(filePath);
3216
3288
  return true;
3217
3289
  } catch {
3218
3290
  return false;
3219
3291
  }
3220
3292
  }
3221
3293
  async function ensureDir(dirPath) {
3222
- await fs9.mkdir(dirPath, { recursive: true });
3294
+ await fs8.mkdir(dirPath, { recursive: true });
3223
3295
  }
3224
3296
  async function copyFile(src, dest) {
3225
- await fs9.copyFile(src, dest);
3297
+ await fs8.copyFile(src, dest);
3226
3298
  }
3227
3299
  function getValheimBaseDir() {
3228
3300
  const platform = getPlatform();
@@ -3276,7 +3348,7 @@ async function listWorldsFromDir(dir, source) {
3276
3348
  const worlds = [];
3277
3349
  const foundNames = /* @__PURE__ */ new Set();
3278
3350
  try {
3279
- const entries = await fs9.readdir(dir, { withFileTypes: true });
3351
+ const entries = await fs8.readdir(dir, { withFileTypes: true });
3280
3352
  for (const entry of entries) {
3281
3353
  if (entry.isFile() && entry.name.endsWith(".db")) {
3282
3354
  if (entry.name.includes(".db.")) continue;
@@ -3284,7 +3356,7 @@ async function listWorldsFromDir(dir, source) {
3284
3356
  const dbPath = path7.join(dir, entry.name);
3285
3357
  const fwlPath = path7.join(dir, `${name}.fwl`);
3286
3358
  if (!await exists2(fwlPath)) continue;
3287
- const dbStat = await fs9.stat(dbPath);
3359
+ const dbStat = await fs8.stat(dbPath);
3288
3360
  foundNames.add(name);
3289
3361
  const backupInfo = parseBackupName(name);
3290
3362
  worlds.push({
@@ -3309,7 +3381,7 @@ async function listWorldsFromDir(dir, source) {
3309
3381
  if (foundNames.has(name)) continue;
3310
3382
  const fwlPath = path7.join(dir, entry.name);
3311
3383
  const dbPath = path7.join(dir, `${name}.db`);
3312
- const fwlStat = await fs9.stat(fwlPath);
3384
+ const fwlStat = await fs8.stat(fwlPath);
3313
3385
  const backupInfo = parseBackupName(name);
3314
3386
  worlds.push({
3315
3387
  name,
@@ -3405,7 +3477,7 @@ async function importWorld(dbPath, fwlPath, targetDir) {
3405
3477
  const targetFwl = path7.join(dir, `${name}.fwl`);
3406
3478
  await copyFile(dbPath, targetDb);
3407
3479
  await copyFile(fwlPath, targetFwl);
3408
- const stat3 = await fs9.stat(targetDb);
3480
+ const stat3 = await fs8.stat(targetDb);
3409
3481
  const serverDir = getDedicatedServerWorldsDir();
3410
3482
  const cloudDir = getCloudWorldsDir();
3411
3483
  const source = dir === serverDir ? "server" : dir === cloudDir ? "cloud" : "local";
@@ -3461,16 +3533,16 @@ async function deleteWorld(worldName, worldsDir) {
3461
3533
  throw new Error(`World "${worldName}" not found`);
3462
3534
  }
3463
3535
  if (dbExists) {
3464
- await fs9.unlink(dbPath);
3536
+ await fs8.unlink(dbPath);
3465
3537
  }
3466
3538
  if (fwlExists) {
3467
- await fs9.unlink(fwlPath);
3539
+ await fs8.unlink(fwlPath);
3468
3540
  }
3469
3541
  try {
3470
- const entries = await fs9.readdir(dir, { withFileTypes: true });
3542
+ const entries = await fs8.readdir(dir, { withFileTypes: true });
3471
3543
  for (const entry of entries) {
3472
3544
  if (entry.name.startsWith(`${worldName}.db.`) || entry.name.startsWith(`${worldName}.fwl.`)) {
3473
- await fs9.unlink(path7.join(dir, entry.name));
3545
+ await fs8.unlink(path7.join(dir, entry.name));
3474
3546
  }
3475
3547
  }
3476
3548
  } catch {
@@ -3588,7 +3660,7 @@ World: ${world.name}`);
3588
3660
  console.log(`Size: ${sizeMb} MB`);
3589
3661
  console.log(`Last modified: ${world.modified.toLocaleString()}`);
3590
3662
  try {
3591
- const fwlContent = await fs10.readFile(world.fwlPath, "utf-8");
3663
+ const fwlContent = await fs9.readFile(world.fwlPath, "utf-8");
3592
3664
  if (fwlContent.length > 0) {
3593
3665
  console.log("");
3594
3666
  console.log(
@@ -3620,8 +3692,8 @@ Importing world '${name}'...`);
3620
3692
  console.log(` From: ${path9}`);
3621
3693
  try {
3622
3694
  try {
3623
- await fs10.stat(dbPath);
3624
- await fs10.stat(fwlPath);
3695
+ await fs9.stat(dbPath);
3696
+ await fs9.stat(fwlPath);
3625
3697
  } catch {
3626
3698
  console.error("\nError: World files not found.");
3627
3699
  console.log(` Expected: ${dbPath}`);
@@ -3721,7 +3793,7 @@ import { useEffect as useEffect3, useMemo as useMemo2, useRef as useRef2, useSta
3721
3793
  // package.json
3722
3794
  var package_default = {
3723
3795
  name: "valheim-oz-dsm",
3724
- version: "1.4.3",
3796
+ version: "1.5.1",
3725
3797
  description: "Land of OZ - Valheim Dedicated Server Manager",
3726
3798
  type: "module",
3727
3799
  bin: {
@@ -3911,6 +3983,16 @@ var useStore = create((set) => ({
3911
3983
  installPercent: 0,
3912
3984
  path: null
3913
3985
  },
3986
+ // Initial Valheim server state
3987
+ valheim: {
3988
+ installed: null,
3989
+ installing: false,
3990
+ installProgress: "",
3991
+ installPercent: 0,
3992
+ path: null,
3993
+ verified: null,
3994
+ buildId: null
3995
+ },
3914
3996
  // Actions
3915
3997
  actions: {
3916
3998
  // Server actions
@@ -4096,6 +4178,37 @@ var useStore = create((set) => ({
4096
4178
  installProgress: "",
4097
4179
  installPercent: 0
4098
4180
  }
4181
+ })),
4182
+ // Valheim server actions
4183
+ setValheimInstalled: (installed) => set((state) => ({
4184
+ valheim: { ...state.valheim, installed }
4185
+ })),
4186
+ setValheimInstalling: (installing) => set((state) => ({
4187
+ valheim: { ...state.valheim, installing }
4188
+ })),
4189
+ setValheimInstallProgress: (message, percent) => set((state) => ({
4190
+ valheim: {
4191
+ ...state.valheim,
4192
+ installProgress: message,
4193
+ installPercent: percent
4194
+ }
4195
+ })),
4196
+ setValheimPath: (path9) => set((state) => ({
4197
+ valheim: { ...state.valheim, path: path9 }
4198
+ })),
4199
+ setValheimVerified: (verified) => set((state) => ({
4200
+ valheim: { ...state.valheim, verified }
4201
+ })),
4202
+ setValheimBuildId: (buildId) => set((state) => ({
4203
+ valheim: { ...state.valheim, buildId }
4204
+ })),
4205
+ resetValheimInstall: () => set((state) => ({
4206
+ valheim: {
4207
+ ...state.valheim,
4208
+ installing: false,
4209
+ installProgress: "",
4210
+ installPercent: 0
4211
+ }
4099
4212
  }))
4100
4213
  }
4101
4214
  }));
@@ -43317,6 +43430,22 @@ var Dashboard = () => {
43317
43430
  );
43318
43431
  const setSteamCmdPath = useStore((s) => s.actions.setSteamCmdPath);
43319
43432
  const resetSteamCmdInstall = useStore((s) => s.actions.resetSteamCmdInstall);
43433
+ const valheimInstalled = useStore((s) => s.valheim.installed);
43434
+ const valheimInstalling = useStore((s) => s.valheim.installing);
43435
+ const valheimProgress = useStore((s) => s.valheim.installProgress);
43436
+ const valheimPercent = useStore((s) => s.valheim.installPercent);
43437
+ const valheimPath = useStore((s) => s.valheim.path);
43438
+ const valheimVerified = useStore((s) => s.valheim.verified);
43439
+ const valheimBuildId = useStore((s) => s.valheim.buildId);
43440
+ const setValheimInstalled = useStore((s) => s.actions.setValheimInstalled);
43441
+ const setValheimInstalling = useStore((s) => s.actions.setValheimInstalling);
43442
+ const setValheimInstallProgress = useStore(
43443
+ (s) => s.actions.setValheimInstallProgress
43444
+ );
43445
+ const setValheimPath = useStore((s) => s.actions.setValheimPath);
43446
+ const setValheimVerified = useStore((s) => s.actions.setValheimVerified);
43447
+ const setValheimBuildId = useStore((s) => s.actions.setValheimBuildId);
43448
+ const resetValheimInstall = useStore((s) => s.actions.resetValheimInstall);
43320
43449
  const { start, stop, restart, update, forceSave } = useServer();
43321
43450
  const [isUpdating2, setIsUpdating] = useState6(false);
43322
43451
  const [updateProgress, setUpdateProgress] = useState6("");
@@ -43338,6 +43467,96 @@ var Dashboard = () => {
43338
43467
  };
43339
43468
  checkSteamCmd2();
43340
43469
  }, [setSteamCmdInstalled, setSteamCmdPath]);
43470
+ useEffect7(() => {
43471
+ if (steamCmdInstalled !== true) return;
43472
+ const checkValheim = async () => {
43473
+ try {
43474
+ const installed = await isValheimInstalled();
43475
+ setValheimInstalled(installed);
43476
+ if (installed) {
43477
+ const paths = getSteamPaths();
43478
+ setValheimPath(paths.valheimDir);
43479
+ const verification = await verifyValheimInstallation();
43480
+ setValheimVerified(verification.valid);
43481
+ if (!verification.valid) {
43482
+ addLog("warn", verification.message);
43483
+ }
43484
+ const buildId = await getInstalledVersion();
43485
+ setValheimBuildId(buildId);
43486
+ }
43487
+ } catch {
43488
+ setValheimInstalled(false);
43489
+ setValheimVerified(false);
43490
+ }
43491
+ };
43492
+ checkValheim();
43493
+ }, [
43494
+ steamCmdInstalled,
43495
+ setValheimInstalled,
43496
+ setValheimPath,
43497
+ setValheimVerified,
43498
+ setValheimBuildId,
43499
+ addLog
43500
+ ]);
43501
+ useEffect7(() => {
43502
+ if (steamCmdInstalled === true && valheimInstalled === false && !valheimInstalling) {
43503
+ const autoInstallValheim = async () => {
43504
+ setValheimInstalling(true);
43505
+ addLog("info", "Auto-installing Valheim Dedicated Server...");
43506
+ try {
43507
+ await installValheim((status2) => {
43508
+ setValheimInstallProgress(status2.message, status2.progress);
43509
+ if (status2.stage === "complete") {
43510
+ addLog(
43511
+ "info",
43512
+ "Valheim Dedicated Server installed successfully!"
43513
+ );
43514
+ }
43515
+ });
43516
+ setValheimInstalled(true);
43517
+ const paths = getSteamPaths();
43518
+ setValheimPath(paths.valheimDir);
43519
+ const verification = await verifyValheimInstallation();
43520
+ setValheimVerified(verification.valid);
43521
+ if (verification.valid) {
43522
+ addLog(
43523
+ "info",
43524
+ `Installation verified at: ${verification.installPath}`
43525
+ );
43526
+ } else {
43527
+ addLog("warn", verification.message);
43528
+ }
43529
+ const buildId = await getInstalledVersion();
43530
+ setValheimBuildId(buildId);
43531
+ if (buildId) {
43532
+ addLog("info", `Valheim build ID: ${buildId}`);
43533
+ }
43534
+ } catch (error2) {
43535
+ addLog(
43536
+ "error",
43537
+ `Valheim installation failed: ${error2 instanceof Error ? error2.message : String(error2)}`
43538
+ );
43539
+ setValheimInstalled(false);
43540
+ setValheimVerified(false);
43541
+ } finally {
43542
+ resetValheimInstall();
43543
+ }
43544
+ };
43545
+ autoInstallValheim();
43546
+ }
43547
+ }, [
43548
+ steamCmdInstalled,
43549
+ valheimInstalled,
43550
+ valheimInstalling,
43551
+ setValheimInstalling,
43552
+ setValheimInstallProgress,
43553
+ setValheimInstalled,
43554
+ setValheimPath,
43555
+ setValheimVerified,
43556
+ setValheimBuildId,
43557
+ resetValheimInstall,
43558
+ addLog
43559
+ ]);
43341
43560
  useEffect7(() => {
43342
43561
  const checkStartupTask = async () => {
43343
43562
  try {
@@ -43373,6 +43592,43 @@ var Dashboard = () => {
43373
43592
  resetSteamCmdInstall();
43374
43593
  }
43375
43594
  };
43595
+ const handleInstallValheim = async () => {
43596
+ closeModal();
43597
+ setValheimInstalling(true);
43598
+ addLog("info", "Starting Valheim Dedicated Server installation...");
43599
+ try {
43600
+ await installValheim((status2) => {
43601
+ setValheimInstallProgress(status2.message, status2.progress);
43602
+ if (status2.stage === "complete") {
43603
+ addLog("info", "Valheim Dedicated Server installed successfully!");
43604
+ }
43605
+ });
43606
+ setValheimInstalled(true);
43607
+ const paths = getSteamPaths();
43608
+ setValheimPath(paths.valheimDir);
43609
+ const verification = await verifyValheimInstallation();
43610
+ setValheimVerified(verification.valid);
43611
+ if (verification.valid) {
43612
+ addLog("info", `Installation verified at: ${verification.installPath}`);
43613
+ } else {
43614
+ addLog("warn", verification.message);
43615
+ }
43616
+ const buildId = await getInstalledVersion();
43617
+ setValheimBuildId(buildId);
43618
+ if (buildId) {
43619
+ addLog("info", `Valheim build ID: ${buildId}`);
43620
+ }
43621
+ } catch (error2) {
43622
+ addLog(
43623
+ "error",
43624
+ `Valheim installation failed: ${error2 instanceof Error ? error2.message : String(error2)}`
43625
+ );
43626
+ setValheimInstalled(false);
43627
+ setValheimVerified(false);
43628
+ } finally {
43629
+ resetValheimInstall();
43630
+ }
43631
+ };
43376
43632
  const handleStopConfirm = () => {
43377
43633
  closeModal();
43378
43634
  stop();
@@ -43444,10 +43700,10 @@ var Dashboard = () => {
43444
43700
  }
43445
43701
  };
43446
43702
  useInput4((input) => {
43447
- if (modalOpen || isUpdating2 || steamCmdInstalling || startupTaskProcessing)
43703
+ if (modalOpen || isUpdating2 || steamCmdInstalling || valheimInstalling || startupTaskProcessing)
43448
43704
  return;
43449
43705
  if (input === "s" || input === "S") {
43450
- if (status === "offline" && steamCmdInstalled) {
43706
+ if (status === "offline" && steamCmdInstalled && valheimInstalled) {
43451
43707
  start();
43452
43708
  addLog("info", "Starting server...");
43453
43709
  }
@@ -43481,7 +43737,7 @@ var Dashboard = () => {
43481
43737
  }
43482
43738
  }
43483
43739
  if (input === "u" || input === "U") {
43484
- if (status === "offline" && steamCmdInstalled) {
43740
+ if (status === "offline" && steamCmdInstalled && valheimInstalled) {
43485
43741
  openModal(
43486
43742
  /* @__PURE__ */ jsx11(
43487
43743
  ConfirmModal,
@@ -43508,6 +43764,21 @@ var Dashboard = () => {
43508
43764
  );
43509
43765
  }
43510
43766
  }
43767
+ if (input === "v" || input === "V") {
43768
+ if (steamCmdInstalled && !valheimInstalling) {
43769
+ const action = valheimInstalled === false ? "Install" : "Reinstall/Verify";
43770
+ openModal(
43771
+ /* @__PURE__ */ jsx11(
43772
+ ConfirmModal,
43773
+ {
43774
+ message: `${action} Valheim Dedicated Server? This may take several minutes.`,
43775
+ onConfirm: handleInstallValheim,
43776
+ onCancel: closeModal
43777
+ }
43778
+ )
43779
+ );
43780
+ }
43781
+ }
43511
43782
  if (input === "f" || input === "F") {
43512
43783
  if (status === "online") {
43513
43784
  handleForceSave();
@@ -43614,6 +43885,28 @@ var Dashboard = () => {
43614
43885
  )
43615
43886
  ] });
43616
43887
  }
43888
+ if (valheimInstalling) {
43889
+ return /* @__PURE__ */ jsxs10(Box11, { flexDirection: "column", flexGrow: 1, padding: 1, children: [
43890
+ /* @__PURE__ */ jsx11(Box11, { marginBottom: 1, children: /* @__PURE__ */ jsx11(Text11, { bold: true, color: theme.primary, children: "\u2500 Dashboard \u2500" }) }),
43891
+ /* @__PURE__ */ jsxs10(
43892
+ Box11,
43893
+ {
43894
+ flexDirection: "column",
43895
+ alignItems: "center",
43896
+ justifyContent: "center",
43897
+ flexGrow: 1,
43898
+ children: [
43899
+ /* @__PURE__ */ jsx11(Spinner, { label: "Installing Valheim Dedicated Server..." }),
43900
+ valheimProgress && /* @__PURE__ */ jsx11(Box11, { marginTop: 1, children: /* @__PURE__ */ jsxs10(Text11, { dimColor: true, children: [
43901
+ valheimProgress,
43902
+ valheimPercent > 0 && ` (${valheimPercent}%)`
43903
+ ] }) }),
43904
+ /* @__PURE__ */ jsx11(Box11, { marginTop: 1, children: /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: "Please wait, this may take several minutes..." }) })
43905
+ ]
43906
+ }
43907
+ )
43908
+ ] });
43909
+ }
43617
43910
  return /* @__PURE__ */ jsxs10(Box11, { flexDirection: "column", flexGrow: 1, padding: 1, children: [
43618
43911
  /* @__PURE__ */ jsx11(Box11, { marginBottom: 1, children: /* @__PURE__ */ jsx11(Text11, { bold: true, color: theme.primary, children: "\u2500 Dashboard \u2500" }) }),
43619
43912
  /* @__PURE__ */ jsxs10(Box11, { flexDirection: "column", marginBottom: 1, children: [
@@ -43629,6 +43922,27 @@ var Dashboard = () => {
43629
43922
  ] })
43630
43923
  ] })
43631
43924
  ] }),
43925
+ /* @__PURE__ */ jsxs10(Box11, { flexDirection: "column", marginBottom: 1, children: [
43926
+ /* @__PURE__ */ jsx11(Text11, { bold: true, children: "Valheim Dedicated Server" }),
43927
+ /* @__PURE__ */ jsxs10(Box11, { marginLeft: 2, flexDirection: "column", children: [
43928
+ /* @__PURE__ */ jsxs10(Box11, { flexShrink: 0, children: [
43929
+ /* @__PURE__ */ jsx11(Text11, { children: "Status: " }),
43930
+ steamCmdInstalled !== true ? /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: "Waiting for SteamCMD..." }) : valheimInstalled === null ? /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: "Checking..." }) : valheimInstalled ? /* @__PURE__ */ jsx11(Text11, { color: theme.success, children: "\u25CF Installed" }) : /* @__PURE__ */ jsx11(Text11, { color: theme.warning, children: "\u25CB Not Installed" })
43931
+ ] }),
43932
+ valheimInstalled && valheimVerified !== null && /* @__PURE__ */ jsxs10(Box11, { flexShrink: 0, children: [
43933
+ /* @__PURE__ */ jsx11(Text11, { children: "Verified: " }),
43934
+ valheimVerified ? /* @__PURE__ */ jsx11(Text11, { color: theme.success, children: "\u25CF Yes" }) : /* @__PURE__ */ jsx11(Text11, { color: theme.error, children: "\u25CB Files Missing" })
43935
+ ] }),
43936
+ valheimInstalled && valheimBuildId && /* @__PURE__ */ jsxs10(Box11, { flexShrink: 0, children: [
43937
+ /* @__PURE__ */ jsx11(Text11, { children: "Build ID: " }),
43938
+ /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: valheimBuildId })
43939
+ ] }),
43940
+ valheimInstalled && valheimPath && /* @__PURE__ */ jsxs10(Box11, { flexShrink: 0, children: [
43941
+ /* @__PURE__ */ jsx11(Text11, { children: "Location: " }),
43942
+ /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: valheimPath })
43943
+ ] })
43944
+ ] })
43945
+ ] }),
43632
43946
  /* @__PURE__ */ jsxs10(Box11, { flexDirection: "column", marginBottom: 1, children: [
43633
43947
  /* @__PURE__ */ jsx11(Text11, { bold: true, children: "Server Status" }),
43634
43948
  /* @__PURE__ */ jsxs10(Box11, { marginLeft: 2, flexDirection: "column", children: [
@@ -43697,7 +44011,17 @@ var Dashboard = () => {
43697
44011
  /* @__PURE__ */ jsx11(Text11, { children: "Install SteamCMD" }),
43698
44012
  /* @__PURE__ */ jsx11(Text11, { color: theme.warning, children: " (required)" })
43699
44013
  ] }) }),
43700
- steamCmdInstalled ? status === "offline" ? /* @__PURE__ */ jsxs10(Box11, { flexDirection: "column", children: [
44014
+ steamCmdInstalled && valheimInstalled === false && !valheimInstalling && /* @__PURE__ */ jsx11(Box11, { marginBottom: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs10(Box11, { flexShrink: 0, children: [
44015
+ /* @__PURE__ */ jsx11(Text11, { color: theme.info, children: "[V] " }),
44016
+ /* @__PURE__ */ jsx11(Text11, { children: "Install Valheim Server" }),
44017
+ /* @__PURE__ */ jsx11(Text11, { color: theme.warning, children: " (required)" })
44018
+ ] }) }),
44019
+ steamCmdInstalled && valheimInstalled && valheimVerified === false && /* @__PURE__ */ jsx11(Box11, { marginBottom: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs10(Box11, { flexShrink: 0, children: [
44020
+ /* @__PURE__ */ jsx11(Text11, { color: theme.warning, children: "[V] " }),
44021
+ /* @__PURE__ */ jsx11(Text11, { children: "Reinstall Valheim Server" }),
44022
+ /* @__PURE__ */ jsx11(Text11, { color: theme.error, children: " (verification failed)" })
44023
+ ] }) }),
44024
+ steamCmdInstalled && valheimInstalled ? status === "offline" ? /* @__PURE__ */ jsxs10(Box11, { flexDirection: "column", children: [
43701
44025
  /* @__PURE__ */ jsxs10(Box11, { flexShrink: 0, children: [
43702
44026
  /* @__PURE__ */ jsx11(Text11, { color: theme.success, children: "[S] " }),
43703
44027
  /* @__PURE__ */ jsx11(Text11, { children: "Start Server" })
@@ -43706,6 +44030,10 @@ var Dashboard = () => {
43706
44030
  /* @__PURE__ */ jsx11(Text11, { color: theme.info, children: "[U] " }),
43707
44031
  /* @__PURE__ */ jsx11(Text11, { children: "Update Server" }),
43708
44032
  updateAvailable && /* @__PURE__ */ jsx11(Text11, { color: theme.warning, children: " \u2605" })
44033
+ ] }),
44034
+ /* @__PURE__ */ jsxs10(Box11, { flexShrink: 0, children: [
44035
+ /* @__PURE__ */ jsx11(Text11, { color: theme.info, children: "[V] " }),
44036
+ /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: "Verify/Reinstall Server" })
43709
44037
  ] })
43710
44038
  ] }) : status === "online" ? /* @__PURE__ */ jsxs10(Box11, { flexDirection: "column", children: [
43711
44039
  /* @__PURE__ */ jsxs10(Box11, { flexShrink: 0, children: [
@@ -43730,7 +44058,7 @@ var Dashboard = () => {
43730
44058
  /* @__PURE__ */ jsx11(Text11, { color: theme.error, children: "[K] " }),
43731
44059
  /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: "Force Kill (if stuck)" })
43732
44060
  ] })
43733
- ] }) : steamCmdInstalled === null ? /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: "Checking SteamCMD status..." }) : /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: "Install SteamCMD to manage server" }),
44061
+ ] }) : steamCmdInstalled === null ? /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: "Checking installation status..." }) : !steamCmdInstalled ? /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: "Install SteamCMD to manage server" }) : valheimInstalled === null ? /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: "Checking Valheim installation..." }) : /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: "Install Valheim to manage server" }),
43734
44062
  /* @__PURE__ */ jsx11(Box11, { marginTop: 1, flexShrink: 0, children: startupTaskProcessing ? /* @__PURE__ */ jsx11(Spinner, { label: "Updating auto-start..." }) : startupTaskRegistered === null ? /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: "Checking auto-start status..." }) : /* @__PURE__ */ jsxs10(Box11, { flexShrink: 0, children: [
43735
44063
  /* @__PURE__ */ jsxs10(
43736
44064
  Text11,
@@ -45655,7 +45983,7 @@ var App = () => {
45655
45983
  };
45656
45984
 
45657
45985
  // src/tui/components/PathInput.tsx
45658
- import fs11 from "fs/promises";
45986
+ import fs10 from "fs/promises";
45659
45987
  import path8 from "path";
45660
45988
  import { Box as Box18, Text as Text17, useInput as useInput11 } from "ink";
45661
45989
  import { useEffect as useEffect13, useState as useState12 } from "react";
@@ -45678,7 +46006,7 @@ function launchTui() {
45678
46006
  }
45679
46007
 
45680
46008
  // src/mod.ts
45681
- var VERSION2 = "1.4.3";
46009
+ var VERSION2 = "1.5.1";
45682
46010
  var APP_NAME = "Land of OZ - Valheim DSM";
45683
46011
 
45684
46012
  // main.ts