valheim-oz-dsm 1.8.1 → 1.8.2
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/README.md +100 -67
- package/dist/main.js +29 -11
- package/dist/main.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,20 +5,22 @@
|
|
|
5
5
|
|
|
6
6
|
## About
|
|
7
7
|
|
|
8
|
-
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
**TL;DR:** A terminal-based Valheim server manager that doesn't need Docker, VMs, or a PhD in sysadmin.
|
|
9
|
+
|
|
10
|
+
This is a dedicated server manager for Valheim that runs directly on your machine—no containers, no virtualization, just TypeScript and Node.js. Born from the "Land of Oz" series of server management tools, this project aims to make hosting a Valheim server as painless as possible.
|
|
11
|
+
|
|
12
|
+
Whether you're running a private server for friends or managing a public realm, this tool handles the boring stuff (SteamCMD updates, crash recovery, config management) so you can focus on the Viking stuff (building, exploring, dying to Deathsquitos).
|
|
13
|
+
|
|
14
|
+
[CONTRIBUTING.md](CONTRIBUTING.md) if you want to help make it better.
|
|
12
15
|
|
|
13
16
|
## Details
|
|
14
17
|
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
art.
|
|
18
|
+
- **Runtime:** Node.js 22.x with TypeScript
|
|
19
|
+
- **TUI Framework:** Ink 6.x—React, but for your terminal
|
|
20
|
+
- **Layout Engine:** Yoga flexbox—the same layout engine that powers React Native
|
|
21
|
+
- **Animations:** (ASCII Motion)[https://ascii-motion.app/]—why settle for static ASCII art when you can have *animated* ASCII art?
|
|
22
|
+
- **State Management:** Zustand
|
|
23
|
+
|
|
22
24
|
|
|
23
25
|
## Quick Start
|
|
24
26
|
|
|
@@ -148,7 +150,7 @@ aesthetic. It prioritizes real-time observability while keeping management tools
|
|
|
148
150
|
front and center. Below is a generalized mockup of the DSM TUI built using React
|
|
149
151
|
via Ink. Motion is created using ASCII Motion.
|
|
150
152
|
|
|
151
|
-
> The Valheim DSM
|
|
153
|
+
> The Valheim DSM interface utilizes a structured three-zone TUI
|
|
152
154
|
> architecture designed for maximum administrative visibility. A bold animated
|
|
153
155
|
> ASCII header anchors the top of the screen, followed by a responsive layout
|
|
154
156
|
> that separates active management from passive monitoring. Where possible, the
|
|
@@ -164,11 +166,12 @@ via Ink. Motion is created using ASCII Motion.
|
|
|
164
166
|
| Layer | Technology | Purpose |
|
|
165
167
|
| ---------------- | ---------------- | ------------------------------------------------ |
|
|
166
168
|
| Runtime | Node.js 22.x | TypeScript-first with tsx execution |
|
|
167
|
-
| TUI Framework | Ink
|
|
168
|
-
|
|
|
169
|
+
| TUI Framework | Ink 6.x | React-based terminal UI with Yoga flexbox layout |
|
|
170
|
+
| UI Library | React 19.x | Component-based rendering to terminal |
|
|
171
|
+
| State Management | Zustand 5.x | Lightweight, React-compatible global state |
|
|
169
172
|
| Animation | ASCII Motion MCP | Animated ASCII art for headers and transitions |
|
|
170
173
|
| Process Control | child_process | Cross-platform subprocess management |
|
|
171
|
-
| Configuration | conf
|
|
174
|
+
| Configuration | conf 13.x | Persistent settings with JSON storage |
|
|
172
175
|
|
|
173
176
|
### Directory Structure
|
|
174
177
|
|
|
@@ -238,7 +241,7 @@ land-of-oz-dsm-valheim/
|
|
|
238
241
|
│ ├── config/
|
|
239
242
|
│ │ ├── mod.ts # Configuration module exports
|
|
240
243
|
│ │ ├── schema.ts # Zod schemas for validation
|
|
241
|
-
│ │ ├── store.ts #
|
|
244
|
+
│ │ ├── store.ts # conf package persistence layer (JSON)
|
|
242
245
|
│ │ └── defaults.ts # Default configuration values
|
|
243
246
|
│ │
|
|
244
247
|
│ ├── valheim/
|
|
@@ -302,9 +305,9 @@ Handles all Steam-related operations:
|
|
|
302
305
|
|
|
303
306
|
Persistent settings management:
|
|
304
307
|
|
|
305
|
-
- **
|
|
306
|
-
- **Zod Validation**: Type-safe schema enforcement
|
|
307
|
-
- **Migration Support**: Handle config version upgrades
|
|
308
|
+
- **conf Package**: Cross-platform JSON-based configuration storage
|
|
309
|
+
- **Zod Validation**: Type-safe schema enforcement with runtime validation
|
|
310
|
+
- **Migration Support**: Handle config version upgrades gracefully
|
|
308
311
|
|
|
309
312
|
#### 6. Valheim Integration (`src/valheim/`)
|
|
310
313
|
|
|
@@ -316,48 +319,78 @@ Game-specific functionality:
|
|
|
316
319
|
|
|
317
320
|
### State Flow
|
|
318
321
|
|
|
319
|
-
```
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
322
|
+
```mermaid
|
|
323
|
+
graph TB
|
|
324
|
+
subgraph "User Interaction Layer"
|
|
325
|
+
TUI["TUI Components (Ink/React)"]
|
|
326
|
+
CLI["CLI Commands"]
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
subgraph "State Management (Zustand)"
|
|
330
|
+
Store["Global Store"]
|
|
331
|
+
ServerState["server: {status, pid, players}"]
|
|
332
|
+
ConfigState["config: {settings, world}"]
|
|
333
|
+
LogState["logs: {entries, filter}"]
|
|
334
|
+
UIState["ui: {activeScreen, modal}"]
|
|
335
|
+
Store --> ServerState
|
|
336
|
+
Store --> ConfigState
|
|
337
|
+
Store --> LogState
|
|
338
|
+
Store --> UIState
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
subgraph "Process Management"
|
|
342
|
+
PM["Server Process Manager"]
|
|
343
|
+
WD["Watchdog (Auto-restart)"]
|
|
344
|
+
LS["Log Stream Parser"]
|
|
345
|
+
PM --> WD
|
|
346
|
+
PM --> LS
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
subgraph "Persistence Layer"
|
|
350
|
+
Conf["conf (JSON Storage)"]
|
|
351
|
+
Worlds["World Files (.db/.fwl)"]
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
subgraph "External Systems"
|
|
355
|
+
Steam["SteamCMD"]
|
|
356
|
+
Valheim["Valheim Server Process"]
|
|
357
|
+
RCON["RCON Client (Optional)"]
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
TUI -->|User Input| Store
|
|
361
|
+
CLI -->|Commands| Store
|
|
362
|
+
|
|
363
|
+
Store -->|Read/Write| Conf
|
|
364
|
+
Store -->|Start/Stop| PM
|
|
365
|
+
Store -->|Send Commands| RCON
|
|
366
|
+
|
|
367
|
+
PM -->|Spawn| Valheim
|
|
368
|
+
PM -->|stdout/stderr| LS
|
|
369
|
+
LS -->|Parsed Logs| LogState
|
|
370
|
+
|
|
371
|
+
Valheim -->|Events| WD
|
|
372
|
+
WD -->|Restart on Crash| PM
|
|
373
|
+
|
|
374
|
+
ConfigState -->|Load| Conf
|
|
375
|
+
Conf -->|Load Worlds| Worlds
|
|
376
|
+
|
|
377
|
+
CLI -->|Install/Update| Steam
|
|
378
|
+
Steam -->|Download| Valheim
|
|
379
|
+
|
|
380
|
+
Store -->|React Updates| TUI
|
|
381
|
+
RCON -.->|Commands| Valheim
|
|
382
|
+
|
|
383
|
+
classDef userLayer fill:#F37A47,stroke:#B63C21,color:#fff
|
|
384
|
+
classDef stateLayer fill:#018DA6,stroke:#01657C,color:#fff
|
|
385
|
+
classDef processLayer fill:#FCF983,stroke:#000,color:#000
|
|
386
|
+
classDef persistLayer fill:#691E11,stroke:#B63C21,color:#fff
|
|
387
|
+
classDef externalLayer fill:#001018,stroke:#01657C,color:#fff
|
|
388
|
+
|
|
389
|
+
class TUI,CLI userLayer
|
|
390
|
+
class Store,ServerState,ConfigState,LogState,UIState stateLayer
|
|
391
|
+
class PM,WD,LS processLayer
|
|
392
|
+
class Conf,Worlds persistLayer
|
|
393
|
+
class Steam,Valheim,RCON externalLayer
|
|
361
394
|
```
|
|
362
395
|
|
|
363
396
|
### Valheim Server Settings
|
|
@@ -383,12 +416,12 @@ The DSM exposes all Valheim dedicated server settings through the TUI:
|
|
|
383
416
|
|
|
384
417
|
### Platform Support
|
|
385
418
|
|
|
386
|
-
| Platform | SteamCMD Path | Valheim Install | Config Storage
|
|
387
|
-
| ------------- | ---------------------------------------- | ------------------------------------------- |
|
|
388
|
-
| Windows | `%LOCALAPPDATA%\steamcmd` | `steamapps\common\Valheim dedicated server` | `%APPDATA%\valheim
|
|
389
|
-
| macOS | `~/Library/Application Support/steamcmd` | `steamapps/common/Valheim dedicated server` | `~/Library/Application Support/valheim
|
|
390
|
-
| Linux (Ubuntu)| `~/.local/share/steamcmd` | `steamapps/common/Valheim dedicated server` | `~/.config/valheim
|
|
391
|
-
| Linux (Other) | `~/.local/share/steamcmd` | `steamapps/common/Valheim dedicated server` | `~/.config/valheim
|
|
419
|
+
| Platform | SteamCMD Path | Valheim Install | Config Storage | Notes |
|
|
420
|
+
| ------------- | ---------------------------------------- | ------------------------------------------- | ------------------------------------------- | ----- |
|
|
421
|
+
| Windows | `%LOCALAPPDATA%\steamcmd` | `steamapps\common\Valheim dedicated server` | `%APPDATA%\oz-valheim` | Fully supported |
|
|
422
|
+
| macOS | `~/Library/Application Support/steamcmd` | `steamapps/common/Valheim dedicated server` | `~/Library/Application Support/oz-valheim` | Fully supported |
|
|
423
|
+
| Linux (Ubuntu)| `~/.local/share/steamcmd` | `steamapps/common/Valheim dedicated server` | `~/.config/oz-valheim` | **Requires 32-bit libs** (see Installation) |
|
|
424
|
+
| Linux (Other) | `~/.local/share/steamcmd` | `steamapps/common/Valheim dedicated server` | `~/.config/oz-valheim` | Fully supported |
|
|
392
425
|
|
|
393
426
|
### Development
|
|
394
427
|
|
package/dist/main.js
CHANGED
|
@@ -4878,7 +4878,7 @@ import { useEffect as useEffect3, useMemo as useMemo2, useRef as useRef2, useSta
|
|
|
4878
4878
|
// package.json
|
|
4879
4879
|
var package_default = {
|
|
4880
4880
|
name: "valheim-oz-dsm",
|
|
4881
|
-
version: "1.8.
|
|
4881
|
+
version: "1.8.2",
|
|
4882
4882
|
description: "Land of OZ - Valheim Dedicated Server Manager",
|
|
4883
4883
|
type: "module",
|
|
4884
4884
|
bin: {
|
|
@@ -45131,22 +45131,29 @@ function useServer() {
|
|
|
45131
45131
|
}, 1e3);
|
|
45132
45132
|
return () => clearInterval(interval);
|
|
45133
45133
|
}, [status, actions]);
|
|
45134
|
+
const rconEnabled = rcon.enabled;
|
|
45135
|
+
const rconPort = rcon.port;
|
|
45136
|
+
const rconPassword = rcon.password;
|
|
45137
|
+
const rconTimeout = rcon.timeout;
|
|
45138
|
+
const rconAutoReconnect = rcon.autoReconnect;
|
|
45139
|
+
const rconInitialized = useRef3(false);
|
|
45134
45140
|
useEffect8(() => {
|
|
45135
|
-
if (!
|
|
45141
|
+
if (!rconEnabled) {
|
|
45136
45142
|
if (rconManager.isConnected()) {
|
|
45137
45143
|
rconManager.disconnect();
|
|
45138
45144
|
actions.setRconConnected(false);
|
|
45139
45145
|
}
|
|
45146
|
+
rconInitialized.current = false;
|
|
45140
45147
|
return;
|
|
45141
45148
|
}
|
|
45142
45149
|
rconManager.initialize(
|
|
45143
45150
|
{
|
|
45144
45151
|
host: "localhost",
|
|
45145
|
-
port:
|
|
45146
|
-
password:
|
|
45147
|
-
timeout:
|
|
45148
|
-
enabled:
|
|
45149
|
-
autoReconnect:
|
|
45152
|
+
port: rconPort,
|
|
45153
|
+
password: rconPassword,
|
|
45154
|
+
timeout: rconTimeout,
|
|
45155
|
+
enabled: rconEnabled,
|
|
45156
|
+
autoReconnect: rconAutoReconnect
|
|
45150
45157
|
},
|
|
45151
45158
|
{
|
|
45152
45159
|
onConnectionStateChange: (state) => {
|
|
@@ -45167,12 +45174,23 @@ function useServer() {
|
|
|
45167
45174
|
// Poll every 10 seconds
|
|
45168
45175
|
}
|
|
45169
45176
|
);
|
|
45177
|
+
rconInitialized.current = true;
|
|
45170
45178
|
return () => {
|
|
45171
|
-
|
|
45179
|
+
if (rconInitialized.current) {
|
|
45180
|
+
rconManager.disconnect();
|
|
45181
|
+
rconInitialized.current = false;
|
|
45182
|
+
}
|
|
45172
45183
|
};
|
|
45173
|
-
}, [
|
|
45184
|
+
}, [
|
|
45185
|
+
rconEnabled,
|
|
45186
|
+
rconPort,
|
|
45187
|
+
rconPassword,
|
|
45188
|
+
rconTimeout,
|
|
45189
|
+
rconAutoReconnect,
|
|
45190
|
+
actions
|
|
45191
|
+
]);
|
|
45174
45192
|
useEffect8(() => {
|
|
45175
|
-
if (status === "online" &&
|
|
45193
|
+
if (status === "online" && rconEnabled && !rconManager.isConnected()) {
|
|
45176
45194
|
const timer = setTimeout(() => {
|
|
45177
45195
|
rconManager.connect().catch((error2) => {
|
|
45178
45196
|
actions.addLog("warn", `RCON connection failed: ${error2}`);
|
|
@@ -45183,7 +45201,7 @@ function useServer() {
|
|
|
45183
45201
|
if (status === "offline" && rconManager.isConnected()) {
|
|
45184
45202
|
rconManager.disconnect();
|
|
45185
45203
|
}
|
|
45186
|
-
}, [status,
|
|
45204
|
+
}, [status, rconEnabled, actions]);
|
|
45187
45205
|
return {
|
|
45188
45206
|
status,
|
|
45189
45207
|
start,
|