1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
import { execFileSync } from "node:child_process";
import { existsSync, readFileSync, writeFileSync, cpSync } from "node:fs";
const { STEAM_USERNAME = "", STEAM_PASSWORD = "" } = process.env;
// Validate Steam credentials
if (STEAM_USERNAME === "anonymous") {
console.log("Using anonymous login. No password needed.");
} else if (!STEAM_USERNAME || !STEAM_PASSWORD) {
console.error(
"Please set STEAM_USERNAME and STEAM_PASSWORD environment variables.\n" +
"If you want to use anonymous login, set STEAM_USERNAME to 'anonymous' and leave STEAM_PASSWORD empty.",
);
process.exit(1);
}
// Install game server via steamcmd
execFileSync(
"steamcmd",
[
"+login",
STEAM_USERNAME,
STEAM_PASSWORD || "",
"+force_install_dir",
"/app",
"+app_update",
"3930080",
"validate",
"+quit",
],
{ stdio: "inherit" },
);
// Apply overlay if it exists
if (existsSync("/overlay")) {
console.log("Applying overlay from /overlay to /app");
cpSync("/overlay", "/app", { recursive: true });
}
// Handle configuration file changes via environment variables
const CONFIG_FIELDS = [
{ name: "MissionDirectory", type: "string" },
{ name: "ModdedServer", type: "boolean" },
{ name: "Hidden", type: "boolean" },
{ name: "ServerName", type: "string" },
{ name: "Password", type: "string" },
{ name: "MaxPlayers", type: "number" },
{ name: "DisableErrorKick", type: "boolean" },
{ name: "NoPlayerStopTime", type: "number" },
{ name: "PostMissionDelay", type: "number" },
{ name: "RotationType", type: "number" },
];
const CONFIG_PATH = "/app/DedicatedServerConfig.json";
const config = JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
for (const { name, type } of CONFIG_FIELDS) {
const envVar = process.env[`CONFIG_${name.toUpperCase()}`];
if (envVar == null || envVar === "") continue;
console.log(`Setting ${name} to ${envVar} in ${CONFIG_PATH}`);
if (!(name in config)) continue;
switch (type) {
case "boolean":
config[name] = envVar === "true";
break;
case "number":
config[name] = Number(envVar);
break;
default:
config[name] = envVar;
break;
}
}
writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2) + "\n");
// Do we have any workshop items to download?
if (process.env.WORKSHOP_ITEMS) {
const itemIds = process.env.WORKSHOP_ITEMS.split(",").map((id) => id.trim());
console.log(`Downloading workshop items: ${itemIds.join(", ")}`);
for (const itemId of itemIds) {
execFileSync(
"steamcmd",
[
"+login",
STEAM_USERNAME,
STEAM_PASSWORD || "",
"+workshop_download_item",
"3930080",
itemId,
"+quit",
],
{ stdio: "inherit" },
);
}
// Move downloaded workshop items to the /app/Mods directory
const steamWorkshopPath = `/home/steam/Steam/steamapps/workshop/content/3930080`;
const modsPath = `/app/Mods`;
for (const itemId of itemIds) {
const sourcePath = `${steamWorkshopPath}/${itemId}`;
if (existsSync(sourcePath)) {
console.log(`Copying workshop item ${itemId} to ${modsPath}`);
cpSync(sourcePath, `${modsPath}/${itemId}`, { recursive: true });
} else {
console.warn(`Workshop item ${itemId} not found at ${sourcePath}`);
}
}
}
// Run the server
execFileSync("sh", ["/app/RunServer.sh"], { stdio: "inherit" });
|