Client LuaCsForBarotrauma
ServerSettingsUI.cs
2 using Microsoft.Xna.Framework;
3 using System;
4 using System.Collections.Generic;
5 using System.Linq;
6 
7 namespace Barotrauma.Networking
8 {
9  partial class ServerSettings : ISerializableEntity
10  {
11  //GUI stuff
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;
16 
17  //UI elements relating to karma, hidden when karma is disabled
18  private readonly List<GUIComponent> karmaElements = new List<GUIComponent>();
19  private GUIDropDown karmaPresetDD;
20  private GUIListBox karmaSettingsList;
21 
22  private GUIComponent extraCargoPanel, monstersEnabledPanel;
23  private GUIButton extraCargoButton, monstersEnabledButton;
24 
25  enum SettingsTab
26  {
27  ServerIdentity,
28  General,
29  Antigriefing,
30  Banlist
31  }
32 
33  public void AssignGUIComponent(string propertyName, GUIComponent component)
34  {
35  GetPropertyData(propertyName).AssignGUIComponent(component);
36  }
37 
38  public void AddToGUIUpdateList()
39  {
40  if (GUI.DisableHUD) { return; }
41 
42  settingsFrame?.AddToGUIUpdateList();
43  }
44 
45  private void CreateSettingsFrame()
46  {
47  foreach (NetPropertyData prop in netProperties.Values)
48  {
49  prop.TempValue = prop.Value;
50  }
51 
52  //background frame
53  settingsFrame = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: null);
54  new GUIFrame(new RectTransform(GUI.Canvas.RelativeSize, settingsFrame.RectTransform, Anchor.Center), style: "GUIBackgroundBlocker");
55 
56  new GUIButton(new RectTransform(Vector2.One, settingsFrame.RectTransform), "", style: null).OnClicked += (btn, userData) =>
57  {
58  if (GUI.MouseOn == btn || GUI.MouseOn == btn.TextBlock) { ToggleSettingsFrame(btn, userData); }
59  return true;
60  };
61 
62  new GUIButton(new RectTransform(Vector2.One, settingsFrame.RectTransform), "", style: null)
63  {
64  OnClicked = ToggleSettingsFrame
65  };
66 
67  //center frames
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)
71  {
72  Stretch = true,
73  RelativeSpacing = 0.02f
74  };
75 
76  new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), paddedFrame.RectTransform), TextManager.Get("serversettingsbutton"), font: GUIStyle.LargeFont);
77 
78  var buttonArea = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.04f), paddedFrame.RectTransform), isHorizontal: true)
79  {
80  Stretch = true,
81  RelativeSpacing = 0.01f
82  };
83 
84  var tabContent = new GUIFrame(new RectTransform(new Vector2(1.0f, 0.85f), paddedFrame.RectTransform), style: "InnerFrame");
85 
86  //tabs
87  var settingsTabTypes = Enum.GetValues(typeof(SettingsTab)).Cast<SettingsTab>();
88  foreach (var settingsTab in settingsTabTypes)
89  {
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")
92  {
93  UserData = settingsTab,
94  OnClicked = SelectSettingsTab
95  };
96  }
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);
102 
103  //"Close"
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"))
106  {
107  OnClicked = ToggleSettingsFrame
108  };
109 
110  CreateServerIdentityTab(settingsTabs[SettingsTab.ServerIdentity]);
111  CreateGeneralTab(settingsTabs[SettingsTab.General]);
112  CreateAntigriefingTab(settingsTabs[SettingsTab.Antigriefing]);
113  CreateBanlistTab(settingsTabs[SettingsTab.Banlist]);
114 
115  if (GameMain.Client == null ||
116  !GameMain.Client.HasPermission(Networking.ClientPermissions.ManageSettings))
117  {
118  //block all settings if the client doesn't have permission to edit them
119  foreach (var settingsTab in settingsTabs)
120  {
121  SetElementInteractability(settingsTab.Value, false);
122  }
123  }
124  //keep these enabled, so clients can open the panels and see what's enabled even if they can't edit them
125  extraCargoButton.Enabled = monstersEnabledButton.Enabled = true;
126  }
127 
128  private void SetElementInteractability(GUIComponent parent, bool interactable)
129  {
130  foreach (var child in parent.GetAllChildren<GUIComponent>())
131  {
132  child.Enabled = interactable;
133  //make the disabled color slightly less dim (these should be readable, despite being non-interactable)
134  child.DisabledColor = new Color(child.Color, child.Color.A / 255.0f * 0.8f);
135  if (child is GUITextBlock textBlock)
136  {
137  textBlock.DisabledTextColor = new Color(textBlock.TextColor, textBlock.TextColor.A / 255.0f * 0.8f);
138  }
139  }
140  }
141 
142  private void CreateServerIdentityTab(GUIComponent parent)
143  {
144  //changing server visibility on the fly is not supported in dedicated servers
145  if (GameMain.Client?.ClientPeer is not LidgrenClientPeer)
146  {
147  var isPublic = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), parent.RectTransform),
148  TextManager.Get("publicserver"))
149  {
150  ToolTip = TextManager.Get("publicservertooltip")
151  };
152  AssignGUIComponent(nameof(IsPublic), isPublic);
153  }
154 
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)
158  {
159  OverflowClip = true,
160  MaxTextLength = NetConfig.ServerNameMaxLength
161  };
162  serverNameBox.OnDeselected += (textBox, key) =>
163  {
164  if (textBox.Text.IsNullOrWhiteSpace())
165  {
166  textBox.Flash(GUIStyle.Red);
167  if (GameMain.Client != null)
168  {
169  textBox.Text = GameMain.Client.ServerSettings.ServerName;
170  }
171  }
172  GameMain.Client?.ServerSettings.ClientAdminWrite(NetFlags.Properties);
173  };
174  AssignGUIComponent(nameof(ServerName), serverNameBox);
175 
176  // server message *************************************************************************
177 
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))
181  {
182  Visible = true
183  };
184  var serverMessageBox = new GUITextBox(new RectTransform(Vector2.One, serverMessageContainer.Content.RectTransform),
185  style: "GUITextBoxNoBorder", wrap: true, textAlignment: Alignment.TopLeft)
186  {
187  MaxTextLength = NetConfig.ServerMessageMaxLength
188  };
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"));
191  AssignGUIComponent(nameof(ServerMessageText), serverMessageBox);
192 
193  void updateServerMessageScrollBasedOnCaret()
194  {
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)
199  {
200  serverMessageContainer.ScrollBar.BarScroll
201  = (caretY - serverMessageBox.Rect.Top - serverMessageContainer.Rect.Height + bottomCaretExtent)
202  / (serverMessageBox.Rect.Height - serverMessageContainer.Rect.Height);
203  }
204  else if (caretY + topCaretExtent < serverMessageContainer.Rect.Top)
205  {
206  serverMessageContainer.ScrollBar.BarScroll
207  = (caretY - serverMessageBox.Rect.Top + topCaretExtent)
208  / (serverMessageBox.Rect.Height - serverMessageContainer.Rect.Height);
209  }
210  }
211  serverMessageBox.OnSelected += (textBox, key) =>
212  {
213  serverMessageHint.Visible = false;
214  updateServerMessageScrollBasedOnCaret();
215  };
216  serverMessageBox.OnTextChanged += (textBox, text) =>
217  {
218  serverMessageHint.Visible = !textBox.Selected && !textBox.Readonly && string.IsNullOrWhiteSpace(textBox.Text);
219  RefreshServerInfoSize();
220  return true;
221  };
222  serverMessageBox.RectTransform.SizeChanged += RefreshServerInfoSize;
223  motdCharacterCount.TextGetter += () => { return serverMessageBox.Text.Length + " / " + NetConfig.ServerMessageMaxLength; };
224 
225  void RefreshServerInfoSize()
226  {
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();
231  }
232 
233  serverMessageBox.OnEnterPressed += (textBox, text) =>
234  {
235  string str = textBox.Text;
236  int caretIndex = textBox.CaretIndex;
237  textBox.Text = $"{str[..caretIndex]}\n{str[caretIndex..]}";
238  textBox.CaretIndex = caretIndex + 1;
239 
240  return true;
241  };
242  serverMessageBox.OnDeselected += (textBox, key) =>
243  {
244  if (!textBox.Readonly)
245  {
246  GameMain.Client?.ServerSettings?.ClientAdminWrite(NetFlags.Properties);
247  }
248  serverMessageHint.Visible = !textBox.Readonly && string.IsNullOrWhiteSpace(textBox.Text);
249  };
250  serverMessageBox.OnKeyHit += (sender, key) => updateServerMessageScrollBasedOnCaret();
251 
252  // *************************************************************************
253 
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));
257  foreach (PlayStyle playStyle in Enum.GetValues(typeof(PlayStyle)))
258  {
259  playStyleSelection.AddElement(playStyle, TextManager.Get("servertag." + playStyle), TextManager.Get("servertagdescription." + playStyle));
260  }
261  AssignGUIComponent(nameof(PlayStyle), playStyleSelection);
262 
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")
266  {
267  OnClicked = (btn, userdata) => { CreateChangePasswordPrompt(); return true; }
268  };
269 
270  var wrongPasswordBanBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), parent.RectTransform), TextManager.Get("ServerSettingsBanAfterWrongPassword"));
271  AssignGUIComponent(nameof(BanAfterWrongPassword), wrongPasswordBanBox);
272  var allowedPasswordRetries = NetLobbyScreen.CreateLabeledNumberInput(parent, "ServerSettingsPasswordRetriesBeforeBan", 0, 10);
273  AssignGUIComponent(nameof(MaxPasswordRetriesBeforeBan), allowedPasswordRetries);
274 
275  var maxPlayers = NetLobbyScreen.CreateLabeledNumberInput(parent, "MaxPlayers", 0, NetConfig.MaxPlayers);
276  AssignGUIComponent(nameof(MaxPlayers), maxPlayers);
277 
278  // Language
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)
282  {
283  languageDD.AddItem(language.Label, language.Identifier);
284  }
285  languageLabel.InheritTotalChildrenMinHeight();
286  AssignGUIComponent(nameof(Language), languageDD);
287 
288  }
289 
290  private static void CreateChangePasswordPrompt()
291  {
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))
298  {
299  Censor = true
300  };
301 
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));
305 
306  var okButton = passwordMsgBox.Buttons[0];
307  okButton.OnClicked += (_, __) =>
308  {
309  DebugConsole.ExecuteCommand($"setpassword \"{passwordBox.Text}\"");
310  return true;
311  };
312  okButton.OnClicked += passwordMsgBox.Close;
313 
314  var cancelButton = passwordMsgBox.Buttons[1];
315  cancelButton.OnClicked = (_, __) =>
316  {
317  passwordMsgBox?.Close();
318  passwordMsgBox = null;
319  return true;
320  };
321  passwordBox.OnEnterPressed += (_, __) =>
322  {
323  okButton.OnClicked.Invoke(okButton, okButton.UserData);
324  return true;
325  };
326 
327  passwordBox.Select();
328  }
329 
330  private void CreateGeneralTab(GUIComponent parent)
331  {
332  var listBox = new GUIListBox(new RectTransform(Vector2.One, parent.RectTransform), style: "GUIListBoxNoBorder")
333  {
334  AutoHideScrollBar = true,
335  CurrentSelectMode = GUIListBox.SelectMode.None
336  };
337 
338  NetLobbyScreen.CreateSubHeader("serversettingscategory.roundmanagement", listBox.Content);
339 
340  var endVoteBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), listBox.Content.RectTransform),
341  TextManager.Get("ServerSettingsEndRoundVoting"));
342  AssignGUIComponent(nameof(AllowEndVoting), endVoteBox);
343 
344  NetLobbyScreen.CreateLabeledSlider(listBox.Content, headerTag: string.Empty, valueLabelTag: "ServerSettingsEndRoundVotesRequired", tooltipTag: string.Empty, out var slider, out var sliderLabel);
345 
346  LocalizedString endRoundLabel = sliderLabel.Text;
347  slider.Step = 0.2f;
348  slider.Range = new Vector2(0.5f, 1.0f);
349  AssignGUIComponent(nameof(EndVoteRequiredRatio), slider);
350  slider.OnMoved = (GUIScrollBar scrollBar, float barScroll) =>
351  {
352  ((GUITextBlock)scrollBar.UserData).Text = endRoundLabel + " " + (int)MathUtils.Round(scrollBar.BarScrollValue * 100.0f, 10.0f) + " %";
353  return true;
354  };
355  slider.OnMoved(slider, slider.BarScroll);
356 
357  //***********************************************
358 
359  // Sub Selection
360 
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));
364  foreach (SelectionMode selectionMode in Enum.GetValues(typeof(SelectionMode)))
365  {
366  subSelection.AddElement(selectionMode, TextManager.Get(selectionMode.ToString()));
367  }
368  AssignGUIComponent(nameof(SubSelectionMode), subSelection);
369 
370  // Mode Selection
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));
374  foreach (SelectionMode selectionMode in Enum.GetValues(typeof(SelectionMode)))
375  {
376  gameModeSelection.AddElement(selectionMode, TextManager.Get(selectionMode.ToString()));
377  }
378  AssignGUIComponent(nameof(ModeSelectionMode), gameModeSelection);
379 
380  //***********************************************
381 
382  LocalizedString autoRestartDelayLabel = TextManager.Get("ServerSettingsAutoRestartDelay") + " ";
383 
384  var autorestartBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), listBox.Content.RectTransform),
385  TextManager.Get("AutoRestart"));
386  AssignGUIComponent(nameof(AutoRestart), autorestartBox);
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) =>
391  {
392  GUITextBlock text = scrollBar.UserData as GUITextBlock;
393  text.Text = autoRestartDelayLabel + ToolBox.SecondsToReadableTime(scrollBar.BarScrollValue);
394  return true;
395  };
396  AssignGUIComponent(nameof(AutoRestartInterval), startIntervalSlider);
397  startIntervalSlider.OnMoved(startIntervalSlider, startIntervalSlider.BarScroll);
398 
399  //***********************************************
400 
401  var startWhenClientsReady = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), listBox.Content.RectTransform),
402  TextManager.Get("ServerSettingsStartWhenClientsReady"));
403  AssignGUIComponent(nameof(StartWhenClientsReady), startWhenClientsReady);
404 
405  NetLobbyScreen.CreateLabeledSlider(listBox.Content, headerTag: string.Empty, valueLabelTag: "ServerSettingsStartWhenClientsReadyRatio", tooltipTag: string.Empty,
406  out slider, out sliderLabel);
407  LocalizedString clientsReadyRequiredLabel = sliderLabel.Text;
408  slider.Step = 0.2f;
409  slider.Range = new Vector2(0.5f, 1.0f);
410  slider.OnMoved = (GUIScrollBar scrollBar, float barScroll) =>
411  {
412  ((GUITextBlock)scrollBar.UserData).Text = clientsReadyRequiredLabel.Replace("[percentage]", ((int)MathUtils.Round(scrollBar.BarScrollValue * 100.0f, 10.0f)).ToString());
413  return true;
414  };
416  slider.OnMoved(slider, slider.BarScroll);
417 
418  var randomizeLevelBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), listBox.Content.RectTransform), TextManager.Get("ServerSettingsRandomizeSeed"));
419  AssignGUIComponent(nameof(RandomizeSeed), randomizeLevelBox);
420 
421  //***********************************************
422 
423  NetLobbyScreen.CreateSubHeader("serversettingsroundstab", listBox.Content);
424 
425  var voiceChatEnabled = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), listBox.Content.RectTransform),
426  TextManager.Get("ServerSettingsVoiceChatEnabled"));
427  AssignGUIComponent(nameof(VoiceChatEnabled), voiceChatEnabled);
428 
429  var allowSpecBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), listBox.Content.RectTransform), TextManager.Get("ServerSettingsAllowSpectating"));
430  AssignGUIComponent(nameof(AllowSpectating), allowSpecBox);
431 
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>())
436  {
437  losModeSelection.AddElement(losMode, TextManager.Get($"LosMode{losMode}"), TextManager.Get($"LosMode{losMode}.tooltip"));
438  }
439  AssignGUIComponent(nameof(LosMode), losModeSelection);
440 
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>())
445  {
446  healthBarModeSelection.AddElement(healthBarMode, TextManager.Get($"ShowEnemyHealthBars.{healthBarMode}"));
447  }
448  AssignGUIComponent(nameof(ShowEnemyHealthBars), healthBarModeSelection);
449 
450  var disableBotConversationsBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), listBox.Content.RectTransform), TextManager.Get("ServerSettingsDisableBotConversations"));
451  AssignGUIComponent(nameof(DisableBotConversations), disableBotConversationsBox);
452 
453  //***********************************************
454 
455  NetLobbyScreen.CreateSubHeader("serversettingscategory.misc", listBox.Content);
456 
457  var shareSubsBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), listBox.Content.RectTransform), TextManager.Get("ServerSettingsShareSubFiles"));
458  AssignGUIComponent(nameof(AllowFileTransfers), shareSubsBox);
459 
460  var saveLogsBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), listBox.Content.RectTransform), TextManager.Get("ServerSettingsSaveLogs"))
461  {
462  OnSelected = (GUITickBox) =>
463  {
464  //TODO: fix?
465  //showLogButton.Visible = SaveServerLogs;
466  return true;
467  }
468  };
469  AssignGUIComponent(nameof(SaveServerLogs), saveLogsBox);
470 
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, _) =>
477  {
478  if (scrollBar.UserData is not GUITextBlock text) { return false; }
479  text.Text = TextManager.AddPunctuation(
480  ':',
481  newCampaignDefaultSalaryLabel,
482  TextManager.GetWithVariable("percentageformat", "[value]", ((int)Math.Round(scrollBar.BarScrollValue, digits: 0)).ToString()));
483  return true;
484  };
485  AssignGUIComponent(nameof(NewCampaignDefaultSalary), defaultSalarySlider);
486  defaultSalarySlider.OnMoved(defaultSalarySlider, defaultSalarySlider.BarScroll);
487 
488  //--------------------------------------------------------------------------------
489  // game settings
490  //--------------------------------------------------------------------------------
491 
492  GUILayoutGroup buttonHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), listBox.Content.RectTransform), isHorizontal: true, childAnchor: Anchor.BottomLeft)
493  {
494  Stretch = true,
495  RelativeSpacing = 0.05f
496  };
497 
498  const string MonstersEnabledUserdata = "monstersenabled";
499  const string ExtraCargoUserdata = "extracargo";
500 
501  monstersEnabledButton = new GUIButton(new RectTransform(new Vector2(0.5f, 1.0f), buttonHolder.RectTransform),
502  TextManager.Get("ServerSettingsMonsterSpawns"), style: "GUIButtonSmall")
503  {
504  Enabled = !GameMain.NetworkMember.GameStarted
505  };
506  monstersEnabledPanel = CreateMonstersEnabledPanel();
507  monstersEnabledButton.UserData = MonstersEnabledUserdata;
508  monstersEnabledButton.OnClicked = ExtraSettingsButtonClicked;
509 
510  extraCargoButton = new GUIButton(new RectTransform(new Vector2(0.5f, 1.0f), buttonHolder.RectTransform),
511  TextManager.Get("ServerSettingsAdditionalCargo"), style: "GUIButtonSmall")
512  {
513  Enabled = !GameMain.NetworkMember.GameStarted
514  };
515 
516  extraCargoPanel = CreateExtraCargoPanel();
517  extraCargoButton.UserData = ExtraCargoUserdata;
518  extraCargoButton.OnClicked = ExtraSettingsButtonClicked;
519 
520  GUITextBlock.AutoScaleAndNormalize(buttonHolder.Children.Select(c => ((GUIButton)c).TextBlock));
521 
522  bool ExtraSettingsButtonClicked(GUIButton button, object obj)
523  {
524  //the extra settings buttons (monsters enabled, cargo) hold a reference to the panel they're supposed to toggle
525  GUIComponent panel;
526  switch (obj as string)
527  {
528  case MonstersEnabledUserdata:
529  panel = monstersEnabledPanel;
530  break;
531  case ExtraCargoUserdata:
532  panel = extraCargoPanel;
533  break;
534  default:
535  throw new Exception("Unrecognized extra settings button");
536  }
537  if (GameMain.NetworkMember.GameStarted)
538  {
539  panel.Visible = false;
540  button.Enabled = false;
541  return true;
542  }
543  panel.Visible = !panel.Visible;
544  return true;
545  }
546  }
547 
548  private GUIComponent CreateMonstersEnabledPanel()
549  {
550  var monsterFrame = new GUIListBox(new RectTransform(new Vector2(0.5f, 0.7f), settingsTabs[SettingsTab.General].RectTransform, Anchor.BottomLeft, Pivot.BottomRight))
551  {
552  Visible = false,
553  IgnoreLayoutGroups = true
554  };
555 
556  InitMonstersEnabled();
557  List<Identifier> monsterNames = MonsterEnabled.Keys.ToList();
558  tempMonsterEnabled = new Dictionary<Identifier, bool>(MonsterEnabled);
559  foreach (Identifier s in monsterNames)
560  {
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)
564  {
565  Selected = tempMonsterEnabled[s],
566  OnSelected = (GUITickBox tb) =>
567  {
568  tempMonsterEnabled[s] = tb.Selected;
569  return true;
570  }
571  };
572  }
573  monsterFrame.Content.RectTransform.SortChildren((c1, c2) =>
574  {
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);
578  });
579 
580  if (GameMain.Client == null ||
581  !GameMain.Client.HasPermission(Networking.ClientPermissions.ManageSettings))
582  {
583  SetElementInteractability(monsterFrame.Content, false);
584  }
585 
586  return monsterFrame;
587  }
588 
589  private GUIComponent CreateExtraCargoPanel()
590  {
591  var cargoFrame = new GUIFrame(new RectTransform(new Vector2(0.5f, 0.7f), settingsTabs[SettingsTab.General].RectTransform, Anchor.BottomRight, Pivot.BottomLeft))
592  {
593  Visible = false,
594  IgnoreLayoutGroups = true
595  };
596  var cargoContent = new GUILayoutGroup(new RectTransform(new Vector2(0.95f, 0.95f), cargoFrame.RectTransform, Anchor.Center))
597  {
598  Stretch = true
599  };
600 
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) =>
606  {
607  foreach (var child in cargoList.Content.Children)
608  {
609  if (child.UserData is not ItemPrefab itemPrefab) { continue; }
610  child.Visible = string.IsNullOrEmpty(text) || itemPrefab.Name.Contains(text, StringComparison.OrdinalIgnoreCase);
611  }
612  return true;
613  };
614 
615  foreach (ItemPrefab ip in ItemPrefab.Prefabs.OrderBy(ip => ip.Name))
616  {
617  if (ip.AllowAsExtraCargo.HasValue)
618  {
619  if (!ip.AllowAsExtraCargo.Value) { continue; }
620  }
621  else
622  {
623  if (!ip.CanBeBought) { continue; }
624  }
625 
626  var itemFrame = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.15f), cargoList.Content.RectTransform) { MinSize = new Point(0, 30) }, isHorizontal: true)
627  {
628  Stretch = true,
629  UserData = ip,
630  RelativeSpacing = 0.05f
631  };
632 
633  if (ip.InventoryIcon != null || ip.Sprite != null)
634  {
635  GUIImage img = new GUIImage(new RectTransform(new Point(itemFrame.Rect.Height), itemFrame.RectTransform),
636  ip.InventoryIcon ?? ip.Sprite, scaleToFit: true)
637  {
638  CanBeFocused = false
639  };
640  img.Color = img.Sprite == ip.InventoryIcon ? ip.InventoryIconColor : ip.SpriteColor;
641  }
642 
643  new GUITextBlock(new RectTransform(new Vector2(0.75f, 1.0f), itemFrame.RectTransform),
644  ip.Name, font: GUIStyle.SmallFont)
645  {
646  Wrap = true,
647  CanBeFocused = false
648  };
649 
650  ExtraCargo.TryGetValue(ip, out int cargoVal);
651  var amountInput = new GUINumberInput(new RectTransform(new Vector2(0.35f, 1.0f), itemFrame.RectTransform),
652  NumberType.Int, textAlignment: Alignment.CenterLeft)
653  {
654  MinValueInt = 0,
655  MaxValueInt = MaxExtraCargoItemsOfType,
656  IntValue = cargoVal
657  };
658  amountInput.OnValueChanged += (numberInput) =>
659  {
660  if (ExtraCargo.ContainsKey(ip))
661  {
662  ExtraCargo[ip] = numberInput.IntValue;
663  if (numberInput.IntValue <= 0) { ExtraCargo.Remove(ip); }
664  }
665  else if (ExtraCargo.Keys.Count < MaxExtraCargoItemTypes)
666  {
667  ExtraCargo.Add(ip, numberInput.IntValue);
668  }
669  numberInput.IntValue = ExtraCargo.ContainsKey(ip) ? ExtraCargo[ip] : 0;
670  CoroutineManager.Invoke(() =>
671  {
672  foreach (var child in cargoList.Content.GetAllChildren())
673  {
674  if (child.GetChild<GUINumberInput>() is GUINumberInput otherNumberInput)
675  {
676  otherNumberInput.PlusButton.Enabled = ExtraCargo.Keys.Count < MaxExtraCargoItemTypes && otherNumberInput.IntValue < otherNumberInput.MaxValueInt;
677  }
678  }
679  }, 0.0f);
680  };
681  }
682  if (GameMain.Client == null ||
683  !GameMain.Client.HasPermission(Networking.ClientPermissions.ManageSettings))
684  {
685  SetElementInteractability(cargoList.Content, false);
686  }
687 
688  return cargoFrame;
689  }
690 
691  private void CreateAntigriefingTab(GUIComponent parent)
692  {
693  var listBox = new GUIListBox(new RectTransform(Vector2.One, parent.RectTransform), style: "GUIListBoxNoBorder")
694  {
695  AutoHideScrollBar = true,
696  CurrentSelectMode = GUIListBox.SelectMode.None
697  };
698 
699  //--------------------------------------------------------------------------------
700  // antigriefing
701  //--------------------------------------------------------------------------------
702 
703  var tickBoxContainer = new GUIListBox(new RectTransform(new Vector2(1.0f, 0.268f), listBox.Content.RectTransform))
704  {
705  AutoHideScrollBar = true,
706  UseGridLayout = true
707  };
708  tickBoxContainer.Padding *= 2.0f;
709 
710  var allowFriendlyFire = new GUITickBox(new RectTransform(new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
711  TextManager.Get("ServerSettingsAllowFriendlyFire"));
712  AssignGUIComponent(nameof(AllowFriendlyFire), allowFriendlyFire);
713 
714  var allowDragAndDropGive = new GUITickBox(new RectTransform(new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
715  TextManager.Get("ServerSettingsAllowDragAndDropGive"));
716  AssignGUIComponent(nameof(AllowDragAndDropGive), allowDragAndDropGive);
717 
718  var killableNPCs = new GUITickBox(new RectTransform(new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
719  TextManager.Get("ServerSettingsKillableNPCs"));
720  AssignGUIComponent(nameof(KillableNPCs), killableNPCs);
721 
722  var destructibleOutposts = new GUITickBox(new RectTransform(new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
723  TextManager.Get("ServerSettingsDestructibleOutposts"));
724  AssignGUIComponent(nameof(DestructibleOutposts), destructibleOutposts);
725 
726  var lockAllDefaultWires = new GUITickBox(new RectTransform(new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
727  TextManager.Get("ServerSettingsLockAllDefaultWires"));
728  AssignGUIComponent(nameof(LockAllDefaultWires), lockAllDefaultWires);
729 
730  var allowRewiring = new GUITickBox(new RectTransform(new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
731  TextManager.Get("ServerSettingsAllowRewiring"));
732  AssignGUIComponent(nameof(AllowRewiring), allowRewiring);
733 
734  var allowWifiChatter = new GUITickBox(new RectTransform(new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
735  TextManager.Get("ServerSettingsAllowWifiChat"));
736  AssignGUIComponent(nameof(AllowLinkingWifiToChat), allowWifiChatter);
737 
738  var allowDisguises = new GUITickBox(new RectTransform(new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
739  TextManager.Get("ServerSettingsAllowDisguises"));
740  AssignGUIComponent(nameof(AllowDisguises), allowDisguises);
741 
742  var allowImmediateItemDeliveryBox = new GUITickBox(new RectTransform(new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
743  TextManager.Get("ServerSettingsImmediateItemDelivery"));
744  AssignGUIComponent(nameof(AllowImmediateItemDelivery), allowImmediateItemDeliveryBox);
745 
746  GUITextBlock.AutoScaleAndNormalize(tickBoxContainer.Content.Children.Select(c => ((GUITickBox)c).TextBlock));
747 
748  tickBoxContainer.RectTransform.MinSize = new Point(0, (int)(tickBoxContainer.Content.Children.First().Rect.Height * 2.0f + tickBoxContainer.Padding.Y + tickBoxContainer.Padding.W));
749 
750  tickBoxContainer.RectTransform.MinSize = new Point(0, (int)(tickBoxContainer.Content.Children.First().Rect.Height * 2.0f + tickBoxContainer.Padding.Y + tickBoxContainer.Padding.W));
751 
752  var voteKickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), listBox.Content.RectTransform),
753  TextManager.Get("ServerSettingsAllowVoteKick"));
754  AssignGUIComponent(nameof(AllowVoteKick), voteKickBox);
755 
756  NetLobbyScreen.CreateLabeledSlider(listBox.Content, headerTag: string.Empty, valueLabelTag: "ServerSettingsKickVotesRequired", tooltipTag: string.Empty, out var slider, out var sliderLabel);
757  LocalizedString votesRequiredLabel = sliderLabel.Text + " ";
758  slider.Step = 0.2f;
759  slider.Range = new Vector2(0.5f, 1.0f);
760  slider.OnMoved = (GUIScrollBar scrollBar, float barScroll) =>
761  {
762  ((GUITextBlock)scrollBar.UserData).Text = votesRequiredLabel + (int)MathUtils.Round(scrollBar.BarScrollValue * 100.0f, 10.0f) + " %";
763  return true;
764  };
765  AssignGUIComponent(nameof(KickVoteRequiredRatio), slider);
766  slider.OnMoved(slider, slider.BarScroll);
767 
768  NetLobbyScreen.CreateLabeledSlider(listBox.Content, headerTag: string.Empty, valueLabelTag: "ServerSettingsAutobanTime", tooltipTag: "ServerSettingsAutobanTime.Tooltip", out slider, out sliderLabel);
769  LocalizedString autobanLabel = sliderLabel.Text + " ";
770  slider.Range = new Vector2(0.0f, MaxAutoBanTime);
771  slider.StepValue = 60.0f * 15.0f; //15 minutes
772  slider.OnMoved = (GUIScrollBar scrollBar, float barScroll) =>
773  {
774  ((GUITextBlock)scrollBar.UserData).Text = autobanLabel + ToolBox.SecondsToReadableTime(scrollBar.BarScrollValue);
775  return true;
776  };
777  AssignGUIComponent(nameof(AutoBanTime), slider);
778  slider.OnMoved(slider, slider.BarScroll);
779 
780  var maximumTransferAmount = NetLobbyScreen.CreateLabeledNumberInput(listBox.Content, "serversettingsmaximumtransferrequest", 0, CampaignMode.MaxMoney, "serversettingsmaximumtransferrequesttooltip");
781  AssignGUIComponent(nameof(MaximumMoneyTransferRequest), maximumTransferAmount);
782 
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);
786  AssignGUIComponent(nameof(LootedMoneyDestination), lootedMoneyDestination);
787 
788  var enableDosProtection = new GUITickBox(new RectTransform(new Vector2(0.5f, 0.0f), listBox.Content.RectTransform), TextManager.Get("ServerSettingsEnableDoSProtection"))
789  {
790  ToolTip = TextManager.Get("ServerSettingsEnableDoSProtectionTooltip")
791  };
792  AssignGUIComponent(nameof(EnableDoSProtection), enableDosProtection);
793 
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, _) =>
800  {
801  GUITextBlock textBlock = (GUITextBlock)scrollBar.UserData;
802  int value = (int)MathF.Floor(scrollBar.BarScrollValue);
803 
804  LocalizedString valueText = value > PacketLimitMin
805  ? value.ToString()
806  : TextManager.Get("ServerSettingsNoLimit");
807 
808  switch (value)
809  {
810  case <= PacketLimitMin:
811  textBlock.TextColor = GUIStyle.Green;
812  scrollBar.ToolTip = packetAmountTooltip;
813  break;
814  case < PacketLimitWarning:
815  textBlock.TextColor = GUIStyle.Red;
816  scrollBar.ToolTip = packetAmountTooltipWarning;
817  break;
818  default:
819  textBlock.TextColor = GUIStyle.TextColorNormal;
820  scrollBar.ToolTip = packetAmountTooltip;
821  break;
822  }
823 
824  textBlock.Text = $"{maxPacketCountLabel} {valueText}";
825  return true;
826  };
827  AssignGUIComponent(nameof(MaxPacketAmount), maxPacketSlider);
828  maxPacketSlider.OnMoved(maxPacketSlider, maxPacketSlider.BarScroll);
829 
830  // karma --------------------------------------------------------------------------
831 
832  NetLobbyScreen.CreateSubHeader("Karma", listBox.Content, toolTipTag: "KarmaExplanation");
833 
834  var karmaBox = new GUITickBox(new RectTransform(new Vector2(0.5f, 1f), listBox.Content.RectTransform), TextManager.Get("ServerSettingsUseKarma"))
835  {
836  ToolTip = TextManager.Get("KarmaExplanation")
837  };
838  AssignGUIComponent(nameof(KarmaEnabled), karmaBox);
839 
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)
842  {
843  karmaPresetDD.AddItem(TextManager.Get("KarmaPreset." + karmaPreset), karmaPreset);
844  }
845  karmaElements.Add(karmaPresetDD);
846 
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))
850  {
851  Spacing = (int)(8 * GUI.Scale)
852  };
853  karmaSettingsList.Padding *= 2.0f;
854 
855  karmaPresetDD.SelectItem(KarmaPreset);
856  SetElementInteractability(karmaSettingsList.Content, !karmaBox.Selected || KarmaPreset != "custom");
857  GameMain.NetworkMember.KarmaManager.CreateSettingsFrame(karmaSettingsList.Content);
858  karmaPresetDD.OnSelected = (selected, obj) =>
859  {
860  string newKarmaPreset = obj as string;
861  if (newKarmaPreset == KarmaPreset) { return true; }
862 
863  List<NetPropertyData> properties = netProperties.Values.ToList();
864  List<object> prevValues = new List<object>();
865  foreach (NetPropertyData prop in netProperties.Values)
866  {
867  prevValues.Add(prop.TempValue);
868  if (prop.GUIComponent != null) { prop.Value = prop.GUIComponentValue; }
869  }
870  if (KarmaPreset == "custom")
871  {
872  GameMain.NetworkMember?.KarmaManager?.SaveCustomPreset();
873  GameMain.NetworkMember?.KarmaManager?.Save();
874  }
875  KarmaPreset = newKarmaPreset;
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++)
881  {
882  properties[i].TempValue = prevValues[i];
883  }
884  return true;
885  };
886  AssignGUIComponent(nameof(KarmaPreset), karmaPresetDD);
887  karmaBox.OnSelected = (tb) =>
888  {
889  SetElementInteractability(karmaSettingsList.Content, !karmaBox.Selected || KarmaPreset != "custom");
890  karmaElements.ForEach(e => e.Visible = tb.Selected);
891  return true;
892  };
893  karmaElements.ForEach(e => e.Visible = KarmaEnabled);
894 
895  listBox.Content.InheritTotalChildrenMinHeight();
896  }
897 
898  private void CreateBanlistTab(GUIComponent parent)
899  {
900  BanList.CreateBanFrame(parent);
901  }
902 
903  private bool SelectSettingsTab(GUIButton button, object obj)
904  {
905  selectedTab = (SettingsTab)obj;
906  foreach (var key in settingsTabs.Keys)
907  {
908  settingsTabs[key].Visible = key == selectedTab;
909  tabButtons[key].Selected = key == selectedTab;
910  }
911  return true;
912  }
913 
914  public void Close()
915  {
916  if (KarmaPreset == "custom")
917  {
918  GameMain.NetworkMember?.KarmaManager?.SaveCustomPreset();
919  GameMain.NetworkMember?.KarmaManager?.Save();
920  }
921  ClientAdminWrite(NetFlags.Properties);
922  foreach (NetPropertyData prop in netProperties.Values)
923  {
924  prop.GUIComponent = null;
925  }
926  settingsFrame = null;
927  //give control of server settings back to elements in the lobby
929  }
930 
931  public bool ToggleSettingsFrame(GUIButton button, object obj)
932  {
933  if (GameMain.NetworkMember == null) { return false; }
934  if (settingsFrame == null)
935  {
936  CreateSettingsFrame();
937  }
938  else
939  {
940  Close();
941  }
942  return false;
943  }
944  }
945 }
OnClickedHandler OnClicked
Definition: GUIButton.cs:16
static NetLobbyScreen NetLobbyScreen
Definition: GameMain.cs:55
static NetworkMember NetworkMember
Definition: GameMain.cs:190
void ClientAdminWrite(NetFlags dataToSend, int? missionTypeOr=null, int? missionTypeAnd=null, int traitorDangerLevel=0)
bool ToggleSettingsFrame(GUIButton button, object obj)
void AssignGUIComponent(string propertyName, GUIComponent component)
NumberType
Definition: Enums.cs:715