2[
WorkbenchPluginAttribute(name:
"Dedicated Server Tool", shortcut:
"Ctrl+Shift+D", wbModules: {
"WorldEditor" }, awesomeFontCode: 0xF233)]
3class SCR_DedicatedServerPlugin : WorldEditorPlugin
9 [
Attribute(
desc:
"Server configuration. Dedicated server cannot be launched without this!",
category:
"Server")]
10 protected ref DedicatedServerPluginCLI m_Config;
13 protected string m_sExecutable;
16 protected string m_sProfile;
18 [
Attribute(
"0",
desc:
"Suppresses all sorts of errors (like asserts), so the game continues without stalling and disconnecting clients.",
category:
"Server")]
19 protected bool m_bNoThrow;
21 [
Attribute(
"", uiwidget:
UIWidgets.ComboBox,
desc:
"Enable Backend logs\n- Basic: Turn on basic logs\n- Http: Turn on logging of Http Response & Requests\n- File: Turn on saving of related (mostly JSON) files send and/or recieved from backend into logs folder and subfolder .backend\n- Trace: Turn on logging of inner Http comm - valid only for libcurl (windows ATM)",
category:
"Server", enums: { ParamEnum(
"None",
"0"), ParamEnum(
"Basic",
"1"), ParamEnum(
"Http",
"2"), ParamEnum(
"File",
"3"), ParamEnum(
"Trace",
"4")})]
22 protected int m_iLogBackend;
24 [
Attribute(
"", uiwidget:
UIWidgets.ComboBox,
desc:
"llows manual rerouting to one of our Backend Environments (only in internal version, retail is baked to production system).\n- Dev: Internal development environment\n- Preprod: Preproduction\n- Submission: Submission (preproduction RC candidate environment for testing by QA)\n- Production: Production, this mean players\n- Local: For working without deployed version on your machine",
category:
"Server", enums: { ParamEnum(
"None",
"0"), ParamEnum(
"Dev",
"1"), ParamEnum(
"Preprod",
"2"), ParamEnum(
"Submission",
"3"), ParamEnum(
"Production",
"4"), ParamEnum(
"Local",
"5")})]
25 protected int m_iBackendEnv;
27 [
Attribute(
"30",
desc:
"Maximum FPS on the server. When 0, no limit will be set.",
category:
"Server")]
28 protected int m_iMaxFPS;
30 [
Attribute(
LogLevel.NORMAL.ToString(),
desc:
"Set the highest shown log level.\nAll others below in the list will be included as well\n(e.g., VERBOSE also enables DEBUG, NORMAL, WARNING, etc, but not SPAM).", uiwidget:
UIWidgets.ComboBox,
category:
"Server", enumType:
LogLevel)]
31 protected int m_iLogLevel;
34 protected string m_sParams;
41 protected bool m_bRunPeers;
44 protected string m_sPeerExecutable;
47 protected ref array<ref PeerConfig> m_aPeersConfig;
49 protected ProcessHandle m_ServerHandle;
52 protected string GetAddonsDirCLI()
55 System.GetCLIParam(
"addonsDir", addonsDir);
60 protected string GetAddonsCLI()
64 array<string> addonsGUIDs = {};
67 foreach (
string GUID : addonsGUIDs)
72 if (!addonIDs.IsEmpty())
84 if (!Workbench.ScriptDialog(
"Start Dedicated Server",
"Configure dedicated server before running it. ",
this))
87 WorldEditor worldEditor = Workbench.GetModule(WorldEditor);
91 string gproj = Workbench.GetCurrentGameProjectFile();
92 string process =
string.Format(
"%1 -gproj=\"%2\"", m_sExecutable, gproj);
95 if (m_Config && m_Config.GetCLI(configParam, api))
97 process +=
" " + configParam;
101 Print(
"Cannot start dedicated server, 'Config' setting is incomplete!",
LogLevel.WARNING);
105 string addonsDir = GetAddonsDirCLI();
106 if (!addonsDir.IsEmpty())
107 process +=
" -addonsDir " + addonsDir;
109 string addonIDs = GetAddonsCLI();
110 if (!addonIDs.IsEmpty())
111 process +=
" -addons " + addonIDs;
114 process +=
string.Format(
" -profile %1", m_sProfile);
117 process +=
" -nothrow";
119 switch (m_iLogBackend)
121 case 1: process +=
" -backendLog";
break;
122 case 2: process +=
" -backendLog Http";
break;
123 case 3: process +=
" -backendLog File";
break;
124 case 4: process +=
" -backendLog Trace";
break;
127 switch (m_iBackendEnv)
129 case 1: process +=
" -backendEnv Dev";
break;
130 case 2: process +=
" -backendEnv Preprod";
break;
131 case 3: process +=
" -backendEnv Submission";
break;
132 case 4: process +=
" -backendEnv Production";
break;
133 case 5: process +=
" -backendEnv Local";
break;
137 process +=
string.Format(
" -maxFPS %1", m_iMaxFPS);
140 process +=
string.Format(
" -logLevel %1",
typename.EnumToString(
LogLevel, m_iLogLevel));
143 process +=
" " + m_sParams;
146 m_ServerHandle = Workbench.RunProcess(process);
147 Print(
string.Format(
"Starting dedicated server: %1", process),
LogLevel.NORMAL);
161 string sCmd = m_sPeerExecutable +
" -gproj \"" + gproj +
"\" ";
163 if (!addonsDir.IsEmpty())
164 sCmd +=
"-addonsDir " + addonsDir +
" ";
166 if (!addonIDs.IsEmpty())
167 sCmd +=
"-addons " + addonIDs +
" ";
173 sCmd +=
"-posX " +
conf.X +
" ";
176 sCmd +=
"-posY " +
conf.Y +
" ";
178 if (
conf.Width != -1)
179 sCmd +=
"-screenWidth " +
conf.Width +
" ";
181 if (
conf.Height != -1)
182 sCmd +=
"-screenHeight " +
conf.Height +
" ";
185 sCmd +=
"-maxFPS " +
conf.MaxFPS +
" ";
187 if (
conf.ForceUpdate)
188 sCmd +=
"-forceupdate ";
193 if (
conf.RplAutoJoin)
196 if (
conf.RplAutoReconnect)
197 sCmd +=
"-rpl-reconnect ";
199 if (
conf.RplDisableTimeout)
200 sCmd +=
"-rpl-timeout-disable ";
203 sCmd +=
"-profile " +
conf.Profile + profileIndex.ToString() +
" ";
206 sCmd +=
conf.Params +
" ";
209 conf.Handle = Workbench.RunProcess(sCmd);
211 Print(
"Peer #" + profileIndex +
" couldn't run. Check if your PeerExecutable or other settings are correct",
LogLevel.ERROR);
216 override void OnGameModeEnded()
224 Workbench.KillProcess(
conf.Handle);
230 Workbench.KillProcess(m_ServerHandle);
235 protected bool ButtonRun()
242 protected bool ButtonClose()
250class DedicatedServerPluginCLI
256 bool GetCLI(out
string outParam, WorldEditorAPI api);
261class DedicatedServerPluginCLI_Server : DedicatedServerPluginCLI
263 [
Attribute(
desc:
"World which the server will start.\nWhen empty, currently opened world will be used.", uiwidget: UIWidgets.ResourceNamePicker,
params:
"ent")]
264 protected ResourceName
m_World;
266 [
Attribute(
desc:
"Mission configuration, can enable settings like metabolism / vehicles, set loading screen image, etc.", uiwidget: UIWidgets.ResourceNamePicker,
params:
"conf class=SCR_MissionHeader")]
267 protected ResourceName m_MissionHeader;
269 [
Attribute(
desc:
"Systems configuration to be run if not using the .gproj default one.", uiwidget: UIWidgets.ResourceNamePicker,
params:
"conf class=SystemSettings")]
270 protected ResourceName m_SystemsConfig;
272 [
Attribute(
desc:
"Optional password for logging-in as administrator (in game, type '#login <password>' in chat)")]
273 protected string m_sAdminPassword;
276 override bool GetCLI(out
string outParam, WorldEditorAPI api)
278 ResourceName worldPath =
m_World;
280 api.GetWorldPath(worldPath);
282 outParam =
string.Format(
"-server \"%1\"", worldPath.GetPath());
285 outParam +=
string.Format(
" -MissionHeader \"%1\"", m_MissionHeader.GetPath());
288 outParam +=
string.Format(
" -worldSystemsConfig \"%1\"", m_SystemsConfig.GetPath());
290 if (m_sAdminPassword)
291 outParam +=
string.Format(
" -adminPassword %1", m_sAdminPassword);
293 return !worldPath.IsEmpty();
299class DedicatedServerPluginCLI_Config : DedicatedServerPluginCLI
301 [
Attribute(
desc:
"JSON server configuration file. Does not work when the game is running with local (i.e., non-workshop) addons!", uiwidget: UIWidgets.ResourceNamePicker,
params:
"json")]
302 protected ResourceName m_Config;
305 override bool GetCLI(out
string outParam, WorldEditorAPI api)
309 Workbench.GetAbsolutePath(m_Config.GetPath(), absPath);
311 outParam =
string.Format(
"-config \"%1\"", absPath);
312 return !m_Config.IsEmpty();
SCR_AIAnimation_Loitering BaseContainerProps
Commanding menu commanding element class.
Configs ServerBrowser KickDialogs conf
UI Textures DeployMenu Briefing conflict_HintBanner_1_UI desc
class WorkbenchDialog_AbortRetryIgnore ButtonAttribute("OK", true)
proto void Print(void var, LogLevel level=LogLevel.NORMAL)
Prints content of variable to console/log.
LogLevel
Enum with severity of the logging message.
SCR_FieldOfViewSettings Attribute