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"));
423 NetLobbyScreen.CreateSubHeader(
"serversettingsroundstab", listBox.Content);
425 var voiceChatEnabled =
new GUITickBox(
new RectTransform(
new Vector2(1.0f, 0.05f), listBox.Content.RectTransform),
426 TextManager.Get(
"ServerSettingsVoiceChatEnabled"));
429 var allowSpecBox =
new GUITickBox(
new RectTransform(
new Vector2(1.0f, 0.05f), listBox.Content.RectTransform), TextManager.Get(
"ServerSettingsAllowSpectating"));
432 var losModeLabel =
new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 0.05f), listBox.Content.RectTransform),
433 TextManager.Get(
"LosEffect"));
434 var losModeSelection =
new GUISelectionCarousel<LosMode>(
new RectTransform(
new Vector2(0.5f, 0.6f), losModeLabel.RectTransform,
Anchor.CenterRight));
435 foreach (var losMode
in Enum.GetValues(typeof(
LosMode)).Cast<LosMode>())
437 losModeSelection.AddElement(losMode, TextManager.Get($
"LosMode{losMode}"), TextManager.Get($
"LosMode{losMode}.tooltip"));
441 var healthBarModeLabel =
new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 0.05f), listBox.Content.RectTransform),
442 TextManager.Get(
"ShowEnemyHealthBars"));
443 var healthBarModeSelection =
new GUISelectionCarousel<EnemyHealthBarMode>(
new RectTransform(
new Vector2(0.5f, 0.6f), healthBarModeLabel.RectTransform,
Anchor.CenterRight));
444 foreach (var healthBarMode
in Enum.GetValues(typeof(
EnemyHealthBarMode)).Cast<EnemyHealthBarMode>())
446 healthBarModeSelection.AddElement(healthBarMode, TextManager.Get($
"ShowEnemyHealthBars.{healthBarMode}"));
450 var disableBotConversationsBox =
new GUITickBox(
new RectTransform(
new Vector2(1.0f, 0.05f), listBox.Content.RectTransform), TextManager.Get(
"ServerSettingsDisableBotConversations"));
455 NetLobbyScreen.CreateSubHeader(
"serversettingscategory.misc", listBox.Content);
457 var shareSubsBox =
new GUITickBox(
new RectTransform(
new Vector2(1.0f, 0.05f), listBox.Content.RectTransform), TextManager.Get(
"ServerSettingsShareSubFiles"));
460 var saveLogsBox =
new GUITickBox(
new RectTransform(
new Vector2(1.0f, 0.05f), listBox.Content.RectTransform), TextManager.Get(
"ServerSettingsSaveLogs"))
462 OnSelected = (GUITickBox) =>
471 LocalizedString newCampaignDefaultSalaryLabel = TextManager.Get(
"ServerSettingsNewCampaignDefaultSalary");
472 NetLobbyScreen.CreateLabeledSlider(listBox.Content, headerTag:
"ServerSettingsNewCampaignDefaultSalary", valueLabelTag:
"ServerSettingsKickVotesRequired", tooltipTag:
"ServerSettingsNewCampaignDefaultSalaryToolTip",
473 out var defaultSalarySlider, out var defaultSalarySliderLabel);
474 defaultSalarySlider.Range =
new Vector2(0, 100);
475 defaultSalarySlider.StepValue = 1;
476 defaultSalarySlider.OnMoved = (scrollBar, _) =>
478 if (scrollBar.UserData is not GUITextBlock text) {
return false; }
479 text.Text = TextManager.AddPunctuation(
481 newCampaignDefaultSalaryLabel,
482 TextManager.GetWithVariable(
"percentageformat",
"[value]", ((
int)Math.Round(scrollBar.BarScrollValue, digits: 0)).ToString()));
486 defaultSalarySlider.OnMoved(defaultSalarySlider, defaultSalarySlider.BarScroll);
492 GUILayoutGroup buttonHolder =
new GUILayoutGroup(
new RectTransform(
new Vector2(1.0f, 0.1f), listBox.Content.RectTransform), isHorizontal:
true, childAnchor:
Anchor.BottomLeft)
495 RelativeSpacing = 0.05f
498 const string MonstersEnabledUserdata =
"monstersenabled";
499 const string ExtraCargoUserdata =
"extracargo";
501 monstersEnabledButton =
new GUIButton(
new RectTransform(
new Vector2(0.5f, 1.0f), buttonHolder.RectTransform),
502 TextManager.Get(
"ServerSettingsMonsterSpawns"), style:
"GUIButtonSmall")
504 Enabled = !GameMain.NetworkMember.GameStarted
506 monstersEnabledPanel = CreateMonstersEnabledPanel();
507 monstersEnabledButton.UserData = MonstersEnabledUserdata;
508 monstersEnabledButton.OnClicked = ExtraSettingsButtonClicked;
510 extraCargoButton =
new GUIButton(
new RectTransform(
new Vector2(0.5f, 1.0f), buttonHolder.RectTransform),
511 TextManager.Get(
"ServerSettingsAdditionalCargo"), style:
"GUIButtonSmall")
513 Enabled = !GameMain.NetworkMember.GameStarted
516 extraCargoPanel = CreateExtraCargoPanel();
517 extraCargoButton.UserData = ExtraCargoUserdata;
518 extraCargoButton.OnClicked = ExtraSettingsButtonClicked;
520 GUITextBlock.AutoScaleAndNormalize(buttonHolder.Children.Select(c => ((GUIButton)c).TextBlock));
522 bool ExtraSettingsButtonClicked(GUIButton button,
object obj)
526 switch (obj as
string)
528 case MonstersEnabledUserdata:
529 panel = monstersEnabledPanel;
531 case ExtraCargoUserdata:
532 panel = extraCargoPanel;
535 throw new Exception(
"Unrecognized extra settings button");
537 if (GameMain.NetworkMember.GameStarted)
539 panel.Visible =
false;
540 button.Enabled =
false;
543 panel.Visible = !panel.Visible;
548 private GUIComponent CreateMonstersEnabledPanel()
550 var monsterFrame =
new GUIListBox(
new RectTransform(
new Vector2(0.5f, 0.7f), settingsTabs[SettingsTab.General].RectTransform,
Anchor.BottomLeft,
Pivot.BottomRight))
553 IgnoreLayoutGroups =
true
556 InitMonstersEnabled();
558 tempMonsterEnabled =
new Dictionary<Identifier, bool>(
MonsterEnabled);
559 foreach (Identifier s
in monsterNames)
561 LocalizedString translatedLabel = TextManager.Get($
"Character.{s}").Fallback(s.Value);
562 var monsterEnabledBox =
new GUITickBox(
new RectTransform(
new Vector2(1.0f, 0.1f), monsterFrame.Content.RectTransform) { MinSize = new Point(0, 25) },
563 label: translatedLabel)
566 OnSelected = (GUITickBox tb) =>
568 tempMonsterEnabled[s] = tb.Selected;
573 monsterFrame.Content.RectTransform.SortChildren((c1, c2) =>
575 var name1 = (c1.GUIComponent as GUITickBox)?.Text ??
string.Empty;
576 var name2 = (c2.GUIComponent as GUITickBox)?.Text ??
string.Empty;
577 return name1.CompareTo(name2);
580 if (GameMain.Client ==
null ||
581 !GameMain.Client.HasPermission(Networking.ClientPermissions.ManageSettings))
583 SetElementInteractability(monsterFrame.Content,
false);
589 private GUIComponent CreateExtraCargoPanel()
591 var cargoFrame =
new GUIFrame(
new RectTransform(
new Vector2(0.5f, 0.7f), settingsTabs[SettingsTab.General].RectTransform,
Anchor.BottomRight,
Pivot.BottomLeft))
594 IgnoreLayoutGroups =
true
596 var cargoContent =
new GUILayoutGroup(
new RectTransform(
new Vector2(0.95f, 0.95f), cargoFrame.RectTransform,
Anchor.Center))
601 var filterText =
new GUITextBlock(
new RectTransform(
new Vector2(1.0f, 0.0f), cargoContent.RectTransform), TextManager.Get(
"serverlog.filter"), font: GUIStyle.SubHeadingFont);
602 var entityFilterBox =
new GUITextBox(
new RectTransform(
new Vector2(0.5f, 1.0f), filterText.RectTransform,
Anchor.CenterRight), font: GUIStyle.Font, createClearButton:
true);
603 filterText.RectTransform.MinSize =
new Point(0, entityFilterBox.RectTransform.MinSize.Y);
604 var cargoList =
new GUIListBox(
new RectTransform(
new Vector2(1.0f, 0.8f), cargoContent.RectTransform));
605 entityFilterBox.OnTextChanged += (textBox, text) =>
607 foreach (var child
in cargoList.Content.Children)
609 if (child.UserData is not ItemPrefab itemPrefab) {
continue; }
610 child.Visible =
string.IsNullOrEmpty(text) || itemPrefab.Name.Contains(text, StringComparison.OrdinalIgnoreCase);
615 foreach (ItemPrefab ip
in ItemPrefab.Prefabs.OrderBy(ip => ip.Name))
617 if (ip.AllowAsExtraCargo.HasValue)
619 if (!ip.AllowAsExtraCargo.Value) {
continue; }
623 if (!ip.CanBeBought) {
continue; }
626 var itemFrame =
new GUILayoutGroup(
new RectTransform(
new Vector2(1.0f, 0.15f), cargoList.Content.RectTransform) { MinSize = new Point(0, 30) }, isHorizontal:
true)
630 RelativeSpacing = 0.05f
633 if (ip.InventoryIcon !=
null || ip.Sprite !=
null)
635 GUIImage img =
new GUIImage(
new RectTransform(
new Point(itemFrame.Rect.Height), itemFrame.RectTransform),
636 ip.InventoryIcon ?? ip.Sprite, scaleToFit:
true)
640 img.Color = img.Sprite == ip.InventoryIcon ? ip.InventoryIconColor : ip.SpriteColor;
643 new GUITextBlock(
new RectTransform(
new Vector2(0.75f, 1.0f), itemFrame.RectTransform),
644 ip.Name, font: GUIStyle.SmallFont)
651 var amountInput =
new GUINumberInput(
new RectTransform(
new Vector2(0.35f, 1.0f), itemFrame.RectTransform),
652 NumberType.Int, textAlignment: Alignment.CenterLeft)
658 amountInput.OnValueChanged += (numberInput) =>
663 if (numberInput.IntValue <= 0) {
ExtraCargo.Remove(ip); }
670 CoroutineManager.Invoke(() =>
672 foreach (var child
in cargoList.Content.GetAllChildren())
674 if (child.GetChild<GUINumberInput>() is GUINumberInput otherNumberInput)
682 if (GameMain.Client ==
null ||
683 !GameMain.Client.HasPermission(Networking.ClientPermissions.ManageSettings))
685 SetElementInteractability(cargoList.Content,
false);
691 private void CreateAntigriefingTab(GUIComponent parent)
693 var listBox =
new GUIListBox(
new RectTransform(Vector2.One, parent.RectTransform), style:
"GUIListBoxNoBorder")
695 AutoHideScrollBar =
true,
696 CurrentSelectMode = GUIListBox.SelectMode.None
703 var tickBoxContainer =
new GUIListBox(
new RectTransform(
new Vector2(1.0f, 0.268f), listBox.Content.RectTransform))
705 AutoHideScrollBar =
true,
708 tickBoxContainer.Padding *= 2.0f;
710 var allowFriendlyFire =
new GUITickBox(
new RectTransform(
new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
711 TextManager.Get(
"ServerSettingsAllowFriendlyFire"));
714 var allowDragAndDropGive =
new GUITickBox(
new RectTransform(
new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
715 TextManager.Get(
"ServerSettingsAllowDragAndDropGive"));
718 var killableNPCs =
new GUITickBox(
new RectTransform(
new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
719 TextManager.Get(
"ServerSettingsKillableNPCs"));
722 var destructibleOutposts =
new GUITickBox(
new RectTransform(
new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
723 TextManager.Get(
"ServerSettingsDestructibleOutposts"));
726 var lockAllDefaultWires =
new GUITickBox(
new RectTransform(
new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
727 TextManager.Get(
"ServerSettingsLockAllDefaultWires"));
730 var allowRewiring =
new GUITickBox(
new RectTransform(
new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
731 TextManager.Get(
"ServerSettingsAllowRewiring"));
734 var allowWifiChatter =
new GUITickBox(
new RectTransform(
new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
735 TextManager.Get(
"ServerSettingsAllowWifiChat"));
738 var allowDisguises =
new GUITickBox(
new RectTransform(
new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
739 TextManager.Get(
"ServerSettingsAllowDisguises"));
742 var allowImmediateItemDeliveryBox =
new GUITickBox(
new RectTransform(
new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
743 TextManager.Get(
"ServerSettingsImmediateItemDelivery"));
746 GUITextBlock.AutoScaleAndNormalize(tickBoxContainer.Content.Children.Select(c => ((GUITickBox)c).TextBlock));
748 tickBoxContainer.RectTransform.MinSize =
new Point(0, (
int)(tickBoxContainer.Content.Children.First().Rect.Height * 2.0f + tickBoxContainer.Padding.Y + tickBoxContainer.Padding.W));
750 tickBoxContainer.RectTransform.MinSize =
new Point(0, (
int)(tickBoxContainer.Content.Children.First().Rect.Height * 2.0f + tickBoxContainer.Padding.Y + tickBoxContainer.Padding.W));
752 var voteKickBox =
new GUITickBox(
new RectTransform(
new Vector2(1.0f, 0.05f), listBox.Content.RectTransform),
753 TextManager.Get(
"ServerSettingsAllowVoteKick"));
756 NetLobbyScreen.CreateLabeledSlider(listBox.Content, headerTag:
string.Empty, valueLabelTag:
"ServerSettingsKickVotesRequired", tooltipTag:
string.Empty, out var slider, out var sliderLabel);
757 LocalizedString votesRequiredLabel = sliderLabel.Text +
" ";
759 slider.Range =
new Vector2(0.5f, 1.0f);
760 slider.OnMoved = (GUIScrollBar scrollBar,
float barScroll) =>
762 ((GUITextBlock)scrollBar.UserData).Text = votesRequiredLabel + (int)MathUtils.Round(scrollBar.BarScrollValue * 100.0f, 10.0f) +
" %";
766 slider.OnMoved(slider, slider.BarScroll);
768 NetLobbyScreen.CreateLabeledSlider(listBox.Content, headerTag:
string.Empty, valueLabelTag:
"ServerSettingsAutobanTime", tooltipTag:
"ServerSettingsAutobanTime.Tooltip", out slider, out sliderLabel);
769 LocalizedString autobanLabel = sliderLabel.Text +
" ";
771 slider.StepValue = 60.0f * 15.0f;
772 slider.OnMoved = (GUIScrollBar scrollBar,
float barScroll) =>
774 ((GUITextBlock)scrollBar.UserData).Text = autobanLabel + ToolBox.SecondsToReadableTime(scrollBar.BarScrollValue);
778 slider.OnMoved(slider, slider.BarScroll);
780 var maximumTransferAmount = NetLobbyScreen.CreateLabeledNumberInput(listBox.Content,
"serversettingsmaximumtransferrequest", 0, CampaignMode.MaxMoney,
"serversettingsmaximumtransferrequesttooltip");
783 var lootedMoneyDestination = NetLobbyScreen.CreateLabeledDropdown(listBox.Content,
"serversettingslootedmoneydestination", numElements: 2,
"serversettingslootedmoneydestinationtooltip");
784 lootedMoneyDestination.AddItem(TextManager.Get(
"lootedmoneydestination.bank"),
LootedMoneyDestination.Bank);
785 lootedMoneyDestination.AddItem(TextManager.Get(
"lootedmoneydestination.wallet"),
LootedMoneyDestination.Wallet);
788 var enableDosProtection =
new GUITickBox(
new RectTransform(
new Vector2(0.5f, 0.0f), listBox.Content.RectTransform), TextManager.Get(
"ServerSettingsEnableDoSProtection"))
790 ToolTip = TextManager.Get(
"ServerSettingsEnableDoSProtectionTooltip")
794 NetLobbyScreen.CreateLabeledSlider(listBox.Content, headerTag:
string.Empty, valueLabelTag:
"ServerSettingsMaxPacketAmount", tooltipTag:
string.Empty, out GUIScrollBar maxPacketSlider, out GUITextBlock maxPacketSliderLabel);
795 LocalizedString maxPacketCountLabel = maxPacketSliderLabel.Text;
796 maxPacketSlider.Step = 0.001f;
797 maxPacketSlider.Range =
new Vector2(
PacketLimitMin, PacketLimitMax);
798 maxPacketSlider.ToolTip = packetAmountTooltip;
799 maxPacketSlider.OnMoved = (scrollBar, _) =>
801 GUITextBlock textBlock = (GUITextBlock)scrollBar.UserData;
802 int value = (
int)MathF.Floor(scrollBar.BarScrollValue);
806 : TextManager.Get(
"ServerSettingsNoLimit");
811 textBlock.TextColor = GUIStyle.Green;
812 scrollBar.ToolTip = packetAmountTooltip;
814 case < PacketLimitWarning:
815 textBlock.TextColor = GUIStyle.Red;
816 scrollBar.ToolTip = packetAmountTooltipWarning;
819 textBlock.TextColor = GUIStyle.TextColorNormal;
820 scrollBar.ToolTip = packetAmountTooltip;
824 textBlock.Text = $
"{maxPacketCountLabel} {valueText}";
828 maxPacketSlider.OnMoved(maxPacketSlider, maxPacketSlider.BarScroll);
832 NetLobbyScreen.CreateSubHeader(
"Karma", listBox.Content, toolTipTag:
"KarmaExplanation");
834 var karmaBox =
new GUITickBox(
new RectTransform(
new Vector2(0.5f, 1f), listBox.Content.RectTransform), TextManager.Get(
"ServerSettingsUseKarma"))
836 ToolTip = TextManager.Get(
"KarmaExplanation")
840 karmaPresetDD =
new GUIDropDown(
new RectTransform(
new Vector2(1.0f, 0.05f), listBox.Content.RectTransform));
841 foreach (
string karmaPreset
in GameMain.NetworkMember.KarmaManager.Presets.Keys)
843 karmaPresetDD.AddItem(TextManager.Get(
"KarmaPreset." + karmaPreset), karmaPreset);
845 karmaElements.Add(karmaPresetDD);
847 var karmaSettingsContainer =
new GUIFrame(
new RectTransform(
new Vector2(1.0f, 0.5f), listBox.Content.RectTransform), style:
null);
848 karmaElements.Add(karmaSettingsContainer);
849 karmaSettingsList =
new GUIListBox(
new RectTransform(Vector2.One, karmaSettingsContainer.RectTransform))
851 Spacing = (int)(8 * GUI.Scale)
853 karmaSettingsList.Padding *= 2.0f;
856 SetElementInteractability(karmaSettingsList.Content, !karmaBox.Selected ||
KarmaPreset !=
"custom");
857 GameMain.NetworkMember.KarmaManager.CreateSettingsFrame(karmaSettingsList.Content);
858 karmaPresetDD.OnSelected = (selected, obj) =>
860 string newKarmaPreset = obj as string;
861 if (newKarmaPreset ==
KarmaPreset) {
return true; }
863 List<NetPropertyData> properties = netProperties.Values.ToList();
864 List<object> prevValues =
new List<object>();
865 foreach (NetPropertyData prop
in netProperties.Values)
867 prevValues.Add(prop.TempValue);
868 if (prop.GUIComponent !=
null) { prop.Value = prop.GUIComponentValue; }
872 GameMain.NetworkMember?.KarmaManager?.SaveCustomPreset();
873 GameMain.NetworkMember?.KarmaManager?.Save();
876 GameMain.NetworkMember.KarmaManager.SelectPreset(
KarmaPreset);
877 karmaSettingsList.Content.ClearChildren();
878 GameMain.NetworkMember.KarmaManager.CreateSettingsFrame(karmaSettingsList.Content);
879 SetElementInteractability(karmaSettingsList.Content, !karmaBox.Selected ||
KarmaPreset !=
"custom");
880 for (
int i = 0; i < netProperties.Count; i++)
882 properties[i].TempValue = prevValues[i];
887 karmaBox.OnSelected = (tb) =>
889 SetElementInteractability(karmaSettingsList.Content, !karmaBox.Selected ||
KarmaPreset !=
"custom");
890 karmaElements.ForEach(e => e.Visible = tb.Selected);
895 listBox.Content.InheritTotalChildrenMinHeight();
898 private void CreateBanlistTab(GUIComponent parent)
903 private bool SelectSettingsTab(GUIButton button,
object obj)
905 selectedTab = (SettingsTab)obj;
906 foreach (var key
in settingsTabs.Keys)
908 settingsTabs[key].
Visible = key == selectedTab;
909 tabButtons[key].Selected = key == selectedTab;
922 foreach (NetPropertyData prop
in netProperties.Values)
924 prop.GUIComponent =
null;
926 settingsFrame =
null;
934 if (settingsFrame ==
null)
936 CreateSettingsFrame();
static NetLobbyScreen NetLobbyScreen
static NetworkMember NetworkMember
void AssignComponentsToServerSettings()
GUIComponent CreateBanFrame(GUIComponent parent)
bool StartWhenClientsReady
void ClientAdminWrite(NetFlags dataToSend, int? missionTypeOr=null, int? missionTypeAnd=null, int traitorDangerLevel=0)
bool AllowImmediateItemDelivery
bool ToggleSettingsFrame(GUIButton button, object obj)
const int MaxExtraCargoItemsOfType
const int MaxExtraCargoItemTypes
LanguageIdentifier Language
bool DestructibleOutposts
int MaxPasswordRetriesBeforeBan
float NewCampaignDefaultSalary
LootedMoneyDestination LootedMoneyDestination
float StartWhenClientsReadyRatio
void AddToGUIUpdateList()
SelectionMode ModeSelectionMode
int MaximumMoneyTransferRequest
bool AllowLinkingWifiToChat
float AutoRestartInterval
bool DisableBotConversations
float EndVoteRequiredRatio
void AssignGUIComponent(string propertyName, GUIComponent component)
Dictionary< Identifier, bool > MonsterEnabled
bool AllowDragAndDropGive
SelectionMode SubSelectionMode
Dictionary< ItemPrefab, int > ExtraCargo
EnemyHealthBarMode ShowEnemyHealthBars
bool BanAfterWrongPassword
float KickVoteRequiredRatio