2 using Microsoft.Xna.Framework;
4 using System.Collections.Generic;
9 partial class ServerSettings : ISerializableEntity
12 private GUIFrame settingsFrame;
13 private readonly Dictionary<SettingsTab, GUIComponent> settingsTabs =
new Dictionary<SettingsTab, GUIComponent>();
14 private readonly Dictionary<SettingsTab, GUIButton> tabButtons =
new Dictionary<SettingsTab, GUIButton>();
15 private SettingsTab selectedTab;
18 private readonly List<GUIComponent> karmaElements =
new List<GUIComponent>();
19 private GUIDropDown karmaPresetDD;
20 private GUIListBox karmaSettingsList;
22 private GUIComponent extraCargoPanel, monstersEnabledPanel;
23 private GUIButton extraCargoButton, monstersEnabledButton;
35 GetPropertyData(propertyName).AssignGUIComponent(component);
40 if (GUI.DisableHUD) {
return; }
42 settingsFrame?.AddToGUIUpdateList();
45 private void CreateSettingsFrame()
47 foreach (NetPropertyData prop
in netProperties.Values)
49 prop.TempValue = prop.Value;
54 new GUIFrame(
new RectTransform(GUI.Canvas.RelativeSize, settingsFrame.RectTransform,
Anchor.Center), style:
"GUIBackgroundBlocker");
58 if (GUI.MouseOn == btn || GUI.MouseOn == btn.TextBlock) {
ToggleSettingsFrame(btn, userData); }
62 new GUIButton(
new RectTransform(Vector2.One, settingsFrame.RectTransform),
"", style:
null)
68 GUIFrame innerFrame =
new GUIFrame(
new RectTransform(
new Vector2(0.5f, 0.85f), settingsFrame.RectTransform,
Anchor.Center) { MinSize = new Point(400, 430) });
69 GUILayoutGroup paddedFrame =
new GUILayoutGroup(
new RectTransform(innerFrame.Rect.Size -
new Point(GUI.IntScale(20)), innerFrame.RectTransform,
Anchor.Center),
70 childAnchor:
Anchor.TopCenter)
73 RelativeSpacing = 0.02f
76 new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 0.0f), paddedFrame.RectTransform), TextManager.Get(
"serversettingsbutton"), font: GUIStyle.LargeFont);
78 var buttonArea =
new GUILayoutGroup(
new RectTransform(
new Vector2(1.0f, 0.04f), paddedFrame.RectTransform), isHorizontal:
true)
81 RelativeSpacing = 0.01f
84 var tabContent =
new GUIFrame(
new RectTransform(
new Vector2(1.0f, 0.85f), paddedFrame.RectTransform), style:
"InnerFrame");
87 var settingsTabTypes = Enum.GetValues(typeof(SettingsTab)).Cast<SettingsTab>();
88 foreach (var settingsTab
in settingsTabTypes)
90 settingsTabs[settingsTab] =
new GUILayoutGroup(
new RectTransform(
new Vector2(0.95f, 0.95f), tabContent.RectTransform,
Anchor.Center));
91 tabButtons[settingsTab] =
new GUIButton(
new RectTransform(
new Vector2(0.2f, 1.2f), buttonArea.RectTransform), TextManager.Get($
"ServerSettings{settingsTab}Tab"), style:
"GUITabButton")
93 UserData = settingsTab,
94 OnClicked = SelectSettingsTab
97 GUITextBlock.AutoScaleAndNormalize(tabButtons.Values.Select(b => b.TextBlock));
98 SelectSettingsTab(tabButtons[0], 0);
99 tabButtons[SettingsTab.Banlist].Enabled =
100 GameMain.Client.HasPermission(Networking.ClientPermissions.Ban) ||
101 GameMain.Client.HasPermission(Networking.ClientPermissions.Unban);
104 var buttonContainer =
new GUIFrame(
new RectTransform(
new Vector2(0.95f, 0.05f), paddedFrame.RectTransform), style:
null);
105 var closeButton =
new GUIButton(
new RectTransform(
new Vector2(0.25f, 1.0f), buttonContainer.RectTransform,
Anchor.BottomRight), TextManager.Get(
"Close"))
110 CreateServerIdentityTab(settingsTabs[SettingsTab.ServerIdentity]);
111 CreateGeneralTab(settingsTabs[SettingsTab.General]);
112 CreateAntigriefingTab(settingsTabs[SettingsTab.Antigriefing]);
113 CreateBanlistTab(settingsTabs[SettingsTab.Banlist]);
115 if (GameMain.Client ==
null ||
116 !GameMain.Client.HasPermission(Networking.ClientPermissions.ManageSettings))
119 foreach (var settingsTab
in settingsTabs)
121 SetElementInteractability(settingsTab.Value,
false);
125 extraCargoButton.Enabled = monstersEnabledButton.Enabled =
true;
128 private void SetElementInteractability(GUIComponent parent,
bool interactable)
130 foreach (var child
in parent.GetAllChildren<GUIComponent>())
132 child.Enabled = interactable;
134 child.DisabledColor =
new Color(child.Color, child.Color.A / 255.0f * 0.8f);
135 if (child is GUITextBlock textBlock)
137 textBlock.DisabledTextColor =
new Color(textBlock.TextColor, textBlock.TextColor.A / 255.0f * 0.8f);
142 private void CreateServerIdentityTab(GUIComponent parent)
145 if (GameMain.Client?.ClientPeer is not LidgrenClientPeer)
147 var isPublic =
new GUITickBox(
new RectTransform(
new Vector2(1.0f, 0.05f), parent.RectTransform),
148 TextManager.Get(
"publicserver"))
150 ToolTip = TextManager.Get(
"publicservertooltip")
155 var serverNameLabel =
new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 0.05f), parent.RectTransform), TextManager.Get(
"ServerName"));
156 var serverNameBox =
new GUITextBox(
new RectTransform(
new Vector2(0.5f, 1.0f), serverNameLabel.RectTransform,
Anchor.CenterRight),
157 GameMain.Client.ServerSettings.ServerName)
160 MaxTextLength = NetConfig.ServerNameMaxLength
162 serverNameBox.OnDeselected += (textBox, key) =>
164 if (textBox.Text.IsNullOrWhiteSpace())
166 textBox.Flash(GUIStyle.Red);
167 if (GameMain.Client !=
null)
169 textBox.Text = GameMain.Client.ServerSettings.ServerName;
172 GameMain.Client?.ServerSettings.ClientAdminWrite(
NetFlags.Properties);
178 var motdHeader =
new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 0.05f), parent.RectTransform), TextManager.Get(
"ServerMOTD"));
179 var motdCharacterCount =
new GUITextBlock(
new RectTransform(
new Vector2(0.5f, 1.0f), motdHeader.RectTransform,
Anchor.CenterRight),
string.Empty, textAlignment: Alignment.CenterRight);
180 var serverMessageContainer =
new GUIListBox(
new RectTransform(
new Vector2(1.0f, 0.2f), parent.RectTransform))
184 var serverMessageBox =
new GUITextBox(
new RectTransform(Vector2.One, serverMessageContainer.Content.RectTransform),
185 style:
"GUITextBoxNoBorder", wrap:
true, textAlignment: Alignment.TopLeft)
187 MaxTextLength = NetConfig.ServerMessageMaxLength
189 var serverMessageHint =
new GUITextBlock(
new RectTransform(Vector2.One, serverMessageBox.RectTransform),
190 textColor: Color.DarkGray * 0.6f, textAlignment: Alignment.TopLeft, font: GUIStyle.Font, text: TextManager.Get(
"ClickToWriteServerMessage"));
193 void updateServerMessageScrollBasedOnCaret()
195 float caretY = serverMessageBox.CaretScreenPos.Y;
196 float bottomCaretExtent = serverMessageBox.Font.LineHeight * 1.5f;
197 float topCaretExtent = -serverMessageBox.Font.LineHeight * 0.5f;
198 if (caretY + bottomCaretExtent > serverMessageContainer.Rect.Bottom)
200 serverMessageContainer.ScrollBar.BarScroll
201 = (caretY - serverMessageBox.Rect.Top - serverMessageContainer.Rect.Height + bottomCaretExtent)
202 / (serverMessageBox.Rect.Height - serverMessageContainer.Rect.Height);
204 else if (caretY + topCaretExtent < serverMessageContainer.Rect.Top)
206 serverMessageContainer.ScrollBar.BarScroll
207 = (caretY - serverMessageBox.Rect.Top + topCaretExtent)
208 / (serverMessageBox.Rect.Height - serverMessageContainer.Rect.Height);
211 serverMessageBox.OnSelected += (textBox, key) =>
213 serverMessageHint.Visible =
false;
214 updateServerMessageScrollBasedOnCaret();
216 serverMessageBox.OnTextChanged += (textBox, text) =>
218 serverMessageHint.Visible = !textBox.Selected && !textBox.Readonly &&
string.IsNullOrWhiteSpace(textBox.Text);
219 RefreshServerInfoSize();
222 serverMessageBox.RectTransform.SizeChanged += RefreshServerInfoSize;
223 motdCharacterCount.TextGetter += () => {
return serverMessageBox.Text.Length +
" / " + NetConfig.ServerMessageMaxLength; };
225 void RefreshServerInfoSize()
227 serverMessageHint.Visible = !serverMessageBox.Selected && !serverMessageBox.Readonly &&
string.IsNullOrWhiteSpace(serverMessageBox.Text);
228 Vector2 textSize = serverMessageBox.Font.MeasureString(serverMessageBox.WrappedText);
229 serverMessageBox.RectTransform.NonScaledSize =
new Point(serverMessageBox.RectTransform.NonScaledSize.X, Math.Max(serverMessageContainer.Content.Rect.Height, (
int)textSize.Y + 10));
230 serverMessageContainer.UpdateScrollBarSize();
233 serverMessageBox.OnEnterPressed += (textBox, text) =>
235 string str = textBox.Text;
236 int caretIndex = textBox.CaretIndex;
237 textBox.Text = $
"{str[..caretIndex]}\n{str[caretIndex..]}";
238 textBox.CaretIndex = caretIndex + 1;
242 serverMessageBox.OnDeselected += (textBox, key) =>
244 if (!textBox.Readonly)
246 GameMain.Client?.ServerSettings?.ClientAdminWrite(
NetFlags.Properties);
248 serverMessageHint.Visible = !textBox.Readonly &&
string.IsNullOrWhiteSpace(textBox.Text);
250 serverMessageBox.OnKeyHit += (sender, key) => updateServerMessageScrollBasedOnCaret();
254 var playStyleLayoutLabel =
new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 0.05f), parent.RectTransform),
255 TextManager.Get(
"ServerSettingsPlayStyle"));
256 var playStyleSelection =
new GUISelectionCarousel<PlayStyle>(
new RectTransform(
new Vector2(0.5f, 1.0f), playStyleLayoutLabel.RectTransform,
Anchor.CenterRight));
259 playStyleSelection.AddElement(playStyle, TextManager.Get(
"servertag." + playStyle), TextManager.Get(
"servertagdescription." + playStyle));
263 var passwordLabel =
new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 0.05f), parent.RectTransform), TextManager.Get(
"Password"));
264 new GUIButton(
new RectTransform(
new Vector2(0.5f, 1.0f), passwordLabel.RectTransform,
Anchor.CenterRight),
265 TextManager.Get(
"ServerSettingsSetPassword"), style:
"GUIButtonSmall")
267 OnClicked = (btn, userdata) => { CreateChangePasswordPrompt();
return true; }
270 var wrongPasswordBanBox =
new GUITickBox(
new RectTransform(
new Vector2(1.0f, 0.05f), parent.RectTransform), TextManager.Get(
"ServerSettingsBanAfterWrongPassword"));
272 var allowedPasswordRetries = NetLobbyScreen.CreateLabeledNumberInput(parent,
"ServerSettingsPasswordRetriesBeforeBan", 0, 10);
275 var maxPlayers = NetLobbyScreen.CreateLabeledNumberInput(parent,
"MaxPlayers", 0, NetConfig.MaxPlayers);
279 var languageLabel =
new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 0.0f), parent.RectTransform), TextManager.Get(
"Language"));
280 var languageDD =
new GUIDropDown(
new RectTransform(
new Vector2(0.5f, 1.0f), languageLabel.RectTransform,
Anchor.CenterRight));
281 foreach (var language
in ServerLanguageOptions.Options)
283 languageDD.AddItem(language.Label, language.Identifier);
285 languageLabel.InheritTotalChildrenMinHeight();
290 private static void CreateChangePasswordPrompt()
292 var passwordMsgBox =
new GUIMessageBox(
293 TextManager.Get(
"ServerSettingsSetPassword"),
294 "",
new LocalizedString[] { TextManager.Get(
"OK"), TextManager.Get(
"Cancel") },
295 relativeSize:
new Vector2(0.25f, 0.1f), minSize:
new Point(400, GUI.IntScale(170)));
296 var passwordHolder =
new GUILayoutGroup(
new RectTransform(
new Vector2(1.0f, 0.5f), passwordMsgBox.Content.RectTransform), childAnchor:
Anchor.TopCenter);
297 var passwordBox =
new GUITextBox(
new RectTransform(
new Vector2(0.8f, 1f), passwordHolder.RectTransform))
302 passwordMsgBox.Content.Recalculate();
303 passwordMsgBox.Content.InheritTotalChildrenHeight();
304 passwordMsgBox.Content.Parent.RectTransform.MinSize =
new Point(0, (
int)(passwordMsgBox.Content.RectTransform.MinSize.Y / passwordMsgBox.Content.RectTransform.RelativeSize.Y));
306 var okButton = passwordMsgBox.Buttons[0];
307 okButton.OnClicked += (_, __) =>
309 DebugConsole.ExecuteCommand($
"setpassword \"{passwordBox.Text}\"");
312 okButton.OnClicked += passwordMsgBox.Close;
314 var cancelButton = passwordMsgBox.Buttons[1];
315 cancelButton.OnClicked = (_, __) =>
317 passwordMsgBox?.Close();
318 passwordMsgBox =
null;
321 passwordBox.OnEnterPressed += (_, __) =>
323 okButton.OnClicked.Invoke(okButton, okButton.UserData);
327 passwordBox.Select();
330 private void CreateGeneralTab(GUIComponent parent)
332 var listBox =
new GUIListBox(
new RectTransform(Vector2.One, parent.RectTransform), style:
"GUIListBoxNoBorder")
334 AutoHideScrollBar =
true,
335 CurrentSelectMode = GUIListBox.SelectMode.None
338 NetLobbyScreen.CreateSubHeader(
"serversettingscategory.roundmanagement", listBox.Content);
340 var endVoteBox =
new GUITickBox(
new RectTransform(
new Vector2(1.0f, 0.05f), listBox.Content.RectTransform),
341 TextManager.Get(
"ServerSettingsEndRoundVoting"));
344 NetLobbyScreen.CreateLabeledSlider(listBox.Content, headerTag:
string.Empty, valueLabelTag:
"ServerSettingsEndRoundVotesRequired", tooltipTag:
string.Empty, out var slider, out var sliderLabel);
346 LocalizedString endRoundLabel = sliderLabel.Text;
348 slider.Range =
new Vector2(0.5f, 1.0f);
350 slider.OnMoved = (GUIScrollBar scrollBar,
float barScroll) =>
352 ((GUITextBlock)scrollBar.UserData).Text = endRoundLabel +
" " + (int)MathUtils.Round(scrollBar.BarScrollValue * 100.0f, 10.0f) +
" %";
355 slider.OnMoved(slider, slider.BarScroll);
361 var subSelectionLabel =
new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 0.05f), listBox.Content.RectTransform),
362 TextManager.Get(
"ServerSettingsSubSelection"));
363 var subSelection =
new GUISelectionCarousel<SelectionMode>(
new RectTransform(
new Vector2(0.5f, 1.0f), subSelectionLabel.RectTransform,
Anchor.CenterRight));
366 subSelection.AddElement(selectionMode, TextManager.Get(selectionMode.ToString()));
371 var gameModeSelectionLabel =
new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 0.05f), listBox.Content.RectTransform),
372 TextManager.Get(
"ServerSettingsModeSelection"));
373 var gameModeSelection =
new GUISelectionCarousel<SelectionMode>(
new RectTransform(
new Vector2(0.5f, 1.0f), gameModeSelectionLabel.RectTransform,
Anchor.CenterRight));
376 gameModeSelection.AddElement(selectionMode, TextManager.Get(selectionMode.ToString()));
382 LocalizedString autoRestartDelayLabel = TextManager.Get(
"ServerSettingsAutoRestartDelay") +
" ";
384 var autorestartBox =
new GUITickBox(
new RectTransform(
new Vector2(1.0f, 0.05f), listBox.Content.RectTransform),
385 TextManager.Get(
"AutoRestart"));
387 NetLobbyScreen.CreateLabeledSlider(listBox.Content, headerTag:
string.Empty, valueLabelTag:
string.Empty, tooltipTag:
string.Empty,
388 out var startIntervalSlider, out var startIntervalSliderLabel, range:
new Vector2(10.0f, 300.0f));
389 startIntervalSlider.StepValue = 10.0f;
390 startIntervalSlider.OnMoved = (GUIScrollBar scrollBar,
float barScroll) =>
392 GUITextBlock text = scrollBar.UserData as GUITextBlock;
393 text.Text = autoRestartDelayLabel + ToolBox.SecondsToReadableTime(scrollBar.BarScrollValue);
397 startIntervalSlider.OnMoved(startIntervalSlider, startIntervalSlider.BarScroll);
401 var startWhenClientsReady =
new GUITickBox(
new RectTransform(
new Vector2(1.0f, 0.05f), listBox.Content.RectTransform),
402 TextManager.Get(
"ServerSettingsStartWhenClientsReady"));
405 NetLobbyScreen.CreateLabeledSlider(listBox.Content, headerTag:
string.Empty, valueLabelTag:
"ServerSettingsStartWhenClientsReadyRatio", tooltipTag:
string.Empty,
406 out slider, out sliderLabel);
407 LocalizedString clientsReadyRequiredLabel = sliderLabel.Text;
409 slider.Range =
new Vector2(0.5f, 1.0f);
410 slider.OnMoved = (GUIScrollBar scrollBar,
float barScroll) =>
412 ((GUITextBlock)scrollBar.UserData).Text = clientsReadyRequiredLabel.Replace(
"[percentage]", ((
int)MathUtils.Round(scrollBar.BarScrollValue * 100.0f, 10.0f)).ToString());
416 slider.OnMoved(slider, slider.BarScroll);
418 var randomizeLevelBox =
new GUITickBox(
new RectTransform(
new Vector2(1.0f, 0.05f), listBox.Content.RectTransform), TextManager.Get(
"ServerSettingsRandomizeSeed"));
422 NetLobbyScreen.CreateSubHeader(
"gamemode.pvp", listBox.Content);
424 var teamSelectModeLabel =
new GUITextBlock(
425 new RectTransform(
new Vector2(1.0f, 0.05f),
426 listBox.Content.RectTransform),
427 TextManager.Get(
"TeamSelectionMode"));
428 teamSelectModeLabel.ToolTip = TextManager.Get(
"TeamSelectionMode.tooltip");
429 var teamSelectionMode =
new GUISelectionCarousel<PvpTeamSelectionMode>(
430 new RectTransform(
new Vector2(0.5f, 0.6f),
431 teamSelectModeLabel.RectTransform,
435 var optionName = teamSelectionModeOption.ToString();
436 teamSelectionMode.AddElement(teamSelectionModeOption,
437 TextManager.Get($
"TeamSelectionMode.{optionName}"),
438 TextManager.Get($
"TeamSelectionMode.{optionName}.tooltip"));
442 var autoBalanceThresholdLabel =
new GUITextBlock(
443 new RectTransform(
new Vector2(1.0f, 0.05f),
444 listBox.Content.RectTransform),
445 TextManager.Get(
"AutoBalanceThreshold"));
446 var autoBalanceThresholdTooltip = TextManager.Get(
"AutoBalanceThreshold.tooltip");
447 autoBalanceThresholdLabel.ToolTip = autoBalanceThresholdTooltip;
448 var autoBalanceThreshold =
new GUISelectionCarousel<int>(
449 new RectTransform(
new Vector2(0.5f, 0.6f),
450 autoBalanceThresholdLabel.RectTransform,
452 autoBalanceThreshold.AddElement(0, TextManager.Get($
"AutoBalanceThreshold.Off"), autoBalanceThresholdTooltip);
453 autoBalanceThreshold.AddElement(1,
"1", autoBalanceThresholdTooltip);
454 autoBalanceThreshold.AddElement(2,
"2", autoBalanceThresholdTooltip);
455 autoBalanceThreshold.AddElement(3,
"3", autoBalanceThresholdTooltip);
459 NetLobbyScreen.CreateSubHeader(
"serversettingsroundstab", listBox.Content);
461 var voiceChatEnabled =
new GUITickBox(
new RectTransform(
new Vector2(1.0f, 0.05f), listBox.Content.RectTransform),
462 TextManager.Get(
"ServerSettingsVoiceChatEnabled"));
465 var allowSpecBox =
new GUITickBox(
new RectTransform(
new Vector2(1.0f, 0.05f), listBox.Content.RectTransform), TextManager.Get(
"ServerSettingsAllowSpectating"));
468 var losModeLabel =
new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 0.05f), listBox.Content.RectTransform),
469 TextManager.Get(
"LosEffect"));
470 var losModeSelection =
new GUISelectionCarousel<LosMode>(
new RectTransform(
new Vector2(0.5f, 0.6f), losModeLabel.RectTransform,
Anchor.CenterRight));
471 foreach (var losMode
in Enum.GetValues(typeof(
LosMode)).Cast<LosMode>())
473 losModeSelection.AddElement(losMode, TextManager.Get($
"LosMode{losMode}"), TextManager.Get($
"LosMode{losMode}.tooltip"));
477 var healthBarModeLabel =
new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 0.05f), listBox.Content.RectTransform),
478 TextManager.Get(
"ShowEnemyHealthBars"));
479 var healthBarModeSelection =
new GUISelectionCarousel<EnemyHealthBarMode>(
new RectTransform(
new Vector2(0.5f, 0.6f), healthBarModeLabel.RectTransform,
Anchor.CenterRight));
480 foreach (var healthBarMode
in Enum.GetValues(typeof(
EnemyHealthBarMode)).Cast<EnemyHealthBarMode>())
482 healthBarModeSelection.AddElement(healthBarMode, TextManager.Get($
"ShowEnemyHealthBars.{healthBarMode}"));
486 var disableBotConversationsBox =
new GUITickBox(
new RectTransform(
new Vector2(1.0f, 0.05f), listBox.Content.RectTransform), TextManager.Get(
"ServerSettingsDisableBotConversations"));
491 NetLobbyScreen.CreateSubHeader(
"serversettingscategory.misc", listBox.Content);
493 var shareSubsBox =
new GUITickBox(
new RectTransform(
new Vector2(1.0f, 0.05f), listBox.Content.RectTransform), TextManager.Get(
"ServerSettingsShareSubFiles"));
496 var saveLogsBox =
new GUITickBox(
new RectTransform(
new Vector2(1.0f, 0.05f), listBox.Content.RectTransform), TextManager.Get(
"ServerSettingsSaveLogs"))
498 OnSelected = (GUITickBox) =>
507 LocalizedString newCampaignDefaultSalaryLabel = TextManager.Get(
"ServerSettingsNewCampaignDefaultSalary");
508 NetLobbyScreen.CreateLabeledSlider(listBox.Content, headerTag:
"ServerSettingsNewCampaignDefaultSalary", valueLabelTag:
"ServerSettingsKickVotesRequired", tooltipTag:
"ServerSettingsNewCampaignDefaultSalaryToolTip",
509 out var defaultSalarySlider, out var defaultSalarySliderLabel);
510 defaultSalarySlider.Range =
new Vector2(0, 100);
511 defaultSalarySlider.StepValue = 1;
512 defaultSalarySlider.OnMoved = (scrollBar, _) =>
514 if (scrollBar.UserData is not GUITextBlock text) {
return false; }
515 text.Text = TextManager.AddPunctuation(
517 newCampaignDefaultSalaryLabel,
518 TextManager.GetWithVariable(
"percentageformat",
"[value]", ((
int)Math.Round(scrollBar.BarScrollValue, digits: 0)).ToString()));
522 defaultSalarySlider.OnMoved(defaultSalarySlider, defaultSalarySlider.BarScroll);
524 var pvpDisembarkPoints = NetLobbyScreen.CreateLabeledNumberInput(listBox.Content,
"serversettingsdisembarkpoints", 0, 100,
"serversettingsdisembarkpointstooltip");
531 GUILayoutGroup buttonHolder =
new GUILayoutGroup(
new RectTransform(
new Vector2(1.0f, 0.1f), listBox.Content.RectTransform), isHorizontal:
true, childAnchor:
Anchor.BottomLeft)
534 RelativeSpacing = 0.05f
537 const string MonstersEnabledUserdata =
"monstersenabled";
538 const string ExtraCargoUserdata =
"extracargo";
540 monstersEnabledButton =
new GUIButton(
new RectTransform(
new Vector2(0.5f, 1.0f), buttonHolder.RectTransform),
541 TextManager.Get(
"ServerSettingsMonsterSpawns"), style:
"GUIButtonSmall")
543 Enabled = !GameMain.NetworkMember.GameStarted
545 monstersEnabledPanel = CreateMonstersEnabledPanel();
546 monstersEnabledButton.UserData = MonstersEnabledUserdata;
547 monstersEnabledButton.OnClicked = ExtraSettingsButtonClicked;
549 extraCargoButton =
new GUIButton(
new RectTransform(
new Vector2(0.5f, 1.0f), buttonHolder.RectTransform),
550 TextManager.Get(
"ServerSettingsAdditionalCargo"), style:
"GUIButtonSmall")
552 Enabled = !GameMain.NetworkMember.GameStarted
555 extraCargoPanel = CreateExtraCargoPanel();
556 extraCargoButton.UserData = ExtraCargoUserdata;
557 extraCargoButton.OnClicked = ExtraSettingsButtonClicked;
559 GUITextBlock.AutoScaleAndNormalize(buttonHolder.Children.Select(c => ((GUIButton)c).TextBlock));
561 bool ExtraSettingsButtonClicked(GUIButton button,
object obj)
565 switch (obj as
string)
567 case MonstersEnabledUserdata:
568 panel = monstersEnabledPanel;
570 case ExtraCargoUserdata:
571 panel = extraCargoPanel;
574 throw new Exception(
"Unrecognized extra settings button");
576 if (GameMain.NetworkMember.GameStarted)
578 panel.Visible =
false;
579 button.Enabled =
false;
582 panel.Visible = !panel.Visible;
587 private GUIComponent CreateMonstersEnabledPanel()
589 var monsterFrame =
new GUIListBox(
new RectTransform(
new Vector2(0.5f, 0.7f), settingsTabs[SettingsTab.General].RectTransform,
Anchor.BottomLeft,
Pivot.BottomRight))
592 IgnoreLayoutGroups =
true
595 InitMonstersEnabled();
597 tempMonsterEnabled =
new Dictionary<Identifier, bool>(
MonsterEnabled);
598 foreach (Identifier s
in monsterNames)
600 LocalizedString translatedLabel = TextManager.Get($
"Character.{s}").Fallback(s.Value);
601 var monsterEnabledBox =
new GUITickBox(
new RectTransform(
new Vector2(1.0f, 0.1f), monsterFrame.Content.RectTransform) { MinSize = new Point(0, 25) },
602 label: translatedLabel)
605 OnSelected = (GUITickBox tb) =>
607 tempMonsterEnabled[s] = tb.Selected;
612 monsterFrame.Content.RectTransform.SortChildren((c1, c2) =>
614 var name1 = (c1.GUIComponent as GUITickBox)?.Text ??
string.Empty;
615 var name2 = (c2.GUIComponent as GUITickBox)?.Text ??
string.Empty;
616 return name1.CompareTo(name2);
619 if (GameMain.Client ==
null ||
620 !GameMain.Client.HasPermission(Networking.ClientPermissions.ManageSettings))
622 SetElementInteractability(monsterFrame.Content,
false);
628 private GUIComponent CreateExtraCargoPanel()
630 var cargoFrame =
new GUIFrame(
new RectTransform(
new Vector2(0.5f, 0.7f), settingsTabs[SettingsTab.General].RectTransform,
Anchor.BottomRight,
Pivot.BottomLeft))
633 IgnoreLayoutGroups =
true
635 var cargoContent =
new GUILayoutGroup(
new RectTransform(
new Vector2(0.95f, 0.95f), cargoFrame.RectTransform,
Anchor.Center))
640 var filterText =
new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 0.0f), cargoContent.RectTransform), TextManager.Get(
"serverlog.filter"), font: GUIStyle.SubHeadingFont);
641 var entityFilterBox =
new GUITextBox(
new RectTransform(
new Vector2(0.5f, 1.0f), filterText.RectTransform,
Anchor.CenterRight), font: GUIStyle.Font, createClearButton:
true);
642 filterText.RectTransform.MinSize =
new Point(0, entityFilterBox.RectTransform.MinSize.Y);
643 var cargoList =
new GUIListBox(
new RectTransform(
new Vector2(1.0f, 0.8f), cargoContent.RectTransform));
644 entityFilterBox.OnTextChanged += (textBox, text) =>
646 foreach (var child
in cargoList.Content.Children)
648 if (child.UserData is not ItemPrefab itemPrefab) {
continue; }
649 child.Visible =
string.IsNullOrEmpty(text) || itemPrefab.Name.Contains(text, StringComparison.OrdinalIgnoreCase);
654 foreach (ItemPrefab ip
in ItemPrefab.Prefabs.OrderBy(ip => ip.Name))
656 if (ip.AllowAsExtraCargo.HasValue)
658 if (!ip.AllowAsExtraCargo.Value) {
continue; }
662 if (!ip.CanBeBought) {
continue; }
665 var itemFrame =
new GUILayoutGroup(
new RectTransform(
new Vector2(1.0f, 0.15f), cargoList.Content.RectTransform) { MinSize = new Point(0, 30) }, isHorizontal:
true)
669 RelativeSpacing = 0.05f
672 if (ip.InventoryIcon !=
null || ip.Sprite !=
null)
674 GUIImage img =
new GUIImage(
new RectTransform(
new Point(itemFrame.Rect.Height), itemFrame.RectTransform),
675 ip.InventoryIcon ?? ip.Sprite, scaleToFit:
true)
679 img.Color = img.Sprite == ip.InventoryIcon ? ip.InventoryIconColor : ip.SpriteColor;
682 new GUITextBlock(
new RectTransform(
new Vector2(0.75f, 1.0f), itemFrame.RectTransform),
683 ip.Name, font: GUIStyle.SmallFont)
690 var amountInput =
new GUINumberInput(
new RectTransform(
new Vector2(0.35f, 1.0f), itemFrame.RectTransform),
691 NumberType.Int, textAlignment: Alignment.CenterLeft)
697 amountInput.OnValueChanged += (numberInput) =>
702 if (numberInput.IntValue <= 0) {
ExtraCargo.Remove(ip); }
709 CoroutineManager.Invoke(() =>
711 foreach (var child
in cargoList.Content.GetAllChildren())
713 if (child.GetChild<GUINumberInput>() is GUINumberInput otherNumberInput)
721 if (GameMain.Client ==
null ||
722 !GameMain.Client.HasPermission(Networking.ClientPermissions.ManageSettings))
724 SetElementInteractability(cargoList.Content,
false);
730 private void CreateAntigriefingTab(GUIComponent parent)
732 var listBox =
new GUIListBox(
new RectTransform(Vector2.One, parent.RectTransform), style:
"GUIListBoxNoBorder")
734 AutoHideScrollBar =
true,
735 CurrentSelectMode = GUIListBox.SelectMode.None
742 var tickBoxContainer =
new GUIListBox(
new RectTransform(
new Vector2(1.0f, 0.268f), listBox.Content.RectTransform))
744 AutoHideScrollBar =
true,
747 tickBoxContainer.Padding *= 2.0f;
749 var allowFriendlyFire =
new GUITickBox(
new RectTransform(
new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
750 TextManager.Get(
"ServerSettingsAllowFriendlyFire"));
753 var allowDragAndDropGive =
new GUITickBox(
new RectTransform(
new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
754 TextManager.Get(
"ServerSettingsAllowDragAndDropGive"));
757 var killableNPCs =
new GUITickBox(
new RectTransform(
new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
758 TextManager.Get(
"ServerSettingsKillableNPCs"));
761 var destructibleOutposts =
new GUITickBox(
new RectTransform(
new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
762 TextManager.Get(
"ServerSettingsDestructibleOutposts"));
765 var lockAllDefaultWires =
new GUITickBox(
new RectTransform(
new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
766 TextManager.Get(
"ServerSettingsLockAllDefaultWires"));
769 var allowRewiring =
new GUITickBox(
new RectTransform(
new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
770 TextManager.Get(
"ServerSettingsAllowRewiring"));
773 var allowWifiChatter =
new GUITickBox(
new RectTransform(
new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
774 TextManager.Get(
"ServerSettingsAllowWifiChat"));
777 var allowDisguises =
new GUITickBox(
new RectTransform(
new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
778 TextManager.Get(
"ServerSettingsAllowDisguises"));
781 var allowImmediateItemDeliveryBox =
new GUITickBox(
new RectTransform(
new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
782 TextManager.Get(
"ServerSettingsImmediateItemDelivery"));
785 GUITextBlock.AutoScaleAndNormalize(tickBoxContainer.Content.Children.Select(c => ((GUITickBox)c).TextBlock));
787 tickBoxContainer.RectTransform.MinSize =
new Point(0, (
int)(tickBoxContainer.Content.Children.First().Rect.Height * 2.0f + tickBoxContainer.Padding.Y + tickBoxContainer.Padding.W));
789 tickBoxContainer.RectTransform.MinSize =
new Point(0, (
int)(tickBoxContainer.Content.Children.First().Rect.Height * 2.0f + tickBoxContainer.Padding.Y + tickBoxContainer.Padding.W));
791 var voteKickBox =
new GUITickBox(
new RectTransform(
new Vector2(1.0f, 0.05f), listBox.Content.RectTransform),
792 TextManager.Get(
"ServerSettingsAllowVoteKick"));
795 NetLobbyScreen.CreateLabeledSlider(listBox.Content, headerTag:
string.Empty, valueLabelTag:
"ServerSettingsKickVotesRequired", tooltipTag:
string.Empty, out var slider, out var sliderLabel);
796 LocalizedString votesRequiredLabel = sliderLabel.Text +
" ";
798 slider.Range =
new Vector2(0.5f, 1.0f);
799 slider.OnMoved = (GUIScrollBar scrollBar,
float barScroll) =>
801 ((GUITextBlock)scrollBar.UserData).Text = votesRequiredLabel + (int)MathUtils.Round(scrollBar.BarScrollValue * 100.0f, 10.0f) +
" %";
805 slider.OnMoved(slider, slider.BarScroll);
807 NetLobbyScreen.CreateLabeledSlider(listBox.Content, headerTag:
string.Empty, valueLabelTag:
"ServerSettingsAutobanTime", tooltipTag:
"ServerSettingsAutobanTime.Tooltip", out slider, out sliderLabel);
808 LocalizedString autobanLabel = sliderLabel.Text +
" ";
810 slider.StepValue = 60.0f * 15.0f;
811 slider.OnMoved = (GUIScrollBar scrollBar,
float barScroll) =>
813 ((GUITextBlock)scrollBar.UserData).Text = autobanLabel + ToolBox.SecondsToReadableTime(scrollBar.BarScrollValue);
817 slider.OnMoved(slider, slider.BarScroll);
819 var maximumTransferAmount = NetLobbyScreen.CreateLabeledNumberInput(listBox.Content,
"serversettingsmaximumtransferrequest", 0, CampaignMode.MaxMoney,
"serversettingsmaximumtransferrequesttooltip");
822 var lootedMoneyDestination = NetLobbyScreen.CreateLabeledDropdown(listBox.Content,
"serversettingslootedmoneydestination", numElements: 2,
"serversettingslootedmoneydestinationtooltip");
823 lootedMoneyDestination.AddItem(TextManager.Get(
"lootedmoneydestination.bank"),
LootedMoneyDestination.Bank);
824 lootedMoneyDestination.AddItem(TextManager.Get(
"lootedmoneydestination.wallet"),
LootedMoneyDestination.Wallet);
827 var enableDosProtection =
new GUITickBox(
new RectTransform(
new Vector2(0.5f, 0.0f), listBox.Content.RectTransform), TextManager.Get(
"ServerSettingsEnableDoSProtection"))
829 ToolTip = TextManager.Get(
"ServerSettingsEnableDoSProtectionTooltip")
833 NetLobbyScreen.CreateLabeledSlider(listBox.Content, headerTag:
string.Empty, valueLabelTag:
"ServerSettingsMaxPacketAmount", tooltipTag:
string.Empty, out GUIScrollBar maxPacketSlider, out GUITextBlock maxPacketSliderLabel);
834 LocalizedString maxPacketCountLabel = maxPacketSliderLabel.Text;
835 maxPacketSlider.Step = 0.001f;
836 maxPacketSlider.Range =
new Vector2(
PacketLimitMin, PacketLimitMax);
837 maxPacketSlider.ToolTip = packetAmountTooltip;
838 maxPacketSlider.OnMoved = (scrollBar, _) =>
840 GUITextBlock textBlock = (GUITextBlock)scrollBar.UserData;
841 int value = (
int)MathF.Floor(scrollBar.BarScrollValue);
845 : TextManager.Get(
"ServerSettingsNoLimit");
850 textBlock.TextColor = GUIStyle.Green;
851 scrollBar.ToolTip = packetAmountTooltip;
853 case < PacketLimitWarning:
854 textBlock.TextColor = GUIStyle.Red;
855 scrollBar.ToolTip = packetAmountTooltipWarning;
858 textBlock.TextColor = GUIStyle.TextColorNormal;
859 scrollBar.ToolTip = packetAmountTooltip;
863 textBlock.Text = $
"{maxPacketCountLabel} {valueText}";
867 maxPacketSlider.OnMoved(maxPacketSlider, maxPacketSlider.BarScroll);
871 NetLobbyScreen.CreateSubHeader(
"Karma", listBox.Content, toolTipTag:
"KarmaExplanation");
873 var karmaBox =
new GUITickBox(
new RectTransform(
new Vector2(0.5f, 1f), listBox.Content.RectTransform), TextManager.Get(
"ServerSettingsUseKarma"))
875 ToolTip = TextManager.Get(
"KarmaExplanation")
879 karmaPresetDD =
new GUIDropDown(
new RectTransform(
new Vector2(1.0f, 0.05f), listBox.Content.RectTransform));
880 foreach (
string karmaPreset
in GameMain.NetworkMember.KarmaManager.Presets.Keys)
882 karmaPresetDD.AddItem(TextManager.Get(
"KarmaPreset." + karmaPreset), karmaPreset);
884 karmaElements.Add(karmaPresetDD);
886 var karmaSettingsContainer =
new GUIFrame(
new RectTransform(
new Vector2(1.0f, 0.5f), listBox.Content.RectTransform), style:
null);
887 karmaElements.Add(karmaSettingsContainer);
888 karmaSettingsList =
new GUIListBox(
new RectTransform(Vector2.One, karmaSettingsContainer.RectTransform))
890 Spacing = (int)(8 * GUI.Scale)
892 karmaSettingsList.Padding *= 2.0f;
895 SetElementInteractability(karmaSettingsList.Content, !karmaBox.Selected ||
KarmaPreset !=
"custom");
896 GameMain.NetworkMember.KarmaManager.CreateSettingsFrame(karmaSettingsList.Content);
897 karmaPresetDD.OnSelected = (selected, obj) =>
899 string newKarmaPreset = obj as string;
900 if (newKarmaPreset ==
KarmaPreset) {
return true; }
902 List<NetPropertyData> properties = netProperties.Values.ToList();
903 List<object> prevValues =
new List<object>();
904 foreach (NetPropertyData prop
in netProperties.Values)
906 prevValues.Add(prop.TempValue);
907 if (prop.GUIComponent !=
null) { prop.Value = prop.GUIComponentValue; }
911 GameMain.NetworkMember?.KarmaManager?.SaveCustomPreset();
912 GameMain.NetworkMember?.KarmaManager?.Save();
915 GameMain.NetworkMember.KarmaManager.SelectPreset(
KarmaPreset);
916 karmaSettingsList.Content.ClearChildren();
917 GameMain.NetworkMember.KarmaManager.CreateSettingsFrame(karmaSettingsList.Content);
918 SetElementInteractability(karmaSettingsList.Content, !karmaBox.Selected ||
KarmaPreset !=
"custom");
919 for (
int i = 0; i < netProperties.Count; i++)
921 properties[i].TempValue = prevValues[i];
926 karmaBox.OnSelected = (tb) =>
928 SetElementInteractability(karmaSettingsList.Content, !karmaBox.Selected ||
KarmaPreset !=
"custom");
929 karmaElements.ForEach(e => e.Visible = tb.Selected);
934 listBox.Content.InheritTotalChildrenMinHeight();
937 private void CreateBanlistTab(GUIComponent parent)
942 private bool SelectSettingsTab(GUIButton button,
object obj)
944 selectedTab = (SettingsTab)obj;
945 foreach (var key
in settingsTabs.Keys)
947 settingsTabs[key].
Visible = key == selectedTab;
948 tabButtons[key].Selected = key == selectedTab;
961 foreach (NetPropertyData prop
in netProperties.Values)
963 prop.GUIComponent =
null;
965 settingsFrame =
null;
973 if (settingsFrame ==
null)
975 CreateSettingsFrame();
static NetLobbyScreen NetLobbyScreen
static NetworkMember NetworkMember
GUIComponent CreateBanFrame(GUIComponent parent)
bool StartWhenClientsReady
bool AllowImmediateItemDelivery
bool ToggleSettingsFrame(GUIButton button, object obj)
int DisembarkPointAllowance
const int MaxExtraCargoItemsOfType
const int MaxExtraCargoItemTypes
LanguageIdentifier Language
bool DestructibleOutposts
int MaxPasswordRetriesBeforeBan
float NewCampaignDefaultSalary
int PvpAutoBalanceThreshold
LootedMoneyDestination LootedMoneyDestination
float StartWhenClientsReadyRatio
void AddToGUIUpdateList()
SelectionMode ModeSelectionMode
int MaximumMoneyTransferRequest
bool AllowLinkingWifiToChat
float AutoRestartInterval
bool DisableBotConversations
void ClientAdminWrite(NetFlags dataToSend, Identifier addedMissionType=default, Identifier removedMissionType=default, int traitorDangerLevel=0)
float EndVoteRequiredRatio
void AssignGUIComponent(string propertyName, GUIComponent component)
Dictionary< Identifier, bool > MonsterEnabled
bool AllowDragAndDropGive
SelectionMode SubSelectionMode
PvpTeamSelectionMode PvpTeamSelectionMode
Dictionary< ItemPrefab, int > ExtraCargo
EnemyHealthBarMode ShowEnemyHealthBars
bool BanAfterWrongPassword
float KickVoteRequiredRatio
void AssignComponentsToServerSettings()