Build 1.1.4.0
This commit is contained in:
+201
-51
@@ -7,8 +7,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
@@ -241,6 +239,7 @@ namespace Barotrauma
|
||||
private GUITickBox filterPassword;
|
||||
private GUITickBox filterFull;
|
||||
private GUITickBox filterEmpty;
|
||||
private GUIDropDown languageDropdown;
|
||||
private Dictionary<Identifier, GUIDropDown> ternaryFilters;
|
||||
private Dictionary<Identifier, GUITickBox> filterTickBoxes;
|
||||
private Dictionary<Identifier, GUITickBox> playStyleTickBoxes;
|
||||
@@ -255,6 +254,7 @@ namespace Barotrauma
|
||||
private TernaryOption filterModdedValue = TernaryOption.Any;
|
||||
|
||||
private ColumnLabel sortedBy;
|
||||
private bool sortedAscending = true;
|
||||
|
||||
private const float sidebarWidth = 0.2f;
|
||||
public ServerListScreen()
|
||||
@@ -425,10 +425,13 @@ namespace Barotrauma
|
||||
ternaryFilters = new Dictionary<Identifier, GUIDropDown>();
|
||||
filterTickBoxes = new Dictionary<Identifier, GUITickBox>();
|
||||
|
||||
RectTransform createFilterRectT()
|
||||
=> new RectTransform(new Vector2(1.0f, elementHeight), filters.Content.RectTransform);
|
||||
|
||||
GUITickBox addTickBox(Identifier key, LocalizedString text = null, bool defaultState = false, bool addTooltip = false)
|
||||
{
|
||||
text ??= TextManager.Get(key);
|
||||
var tickBox = new GUITickBox(new RectTransform(new Vector2(1.0f, elementHeight), filters.Content.RectTransform), text)
|
||||
var tickBox = new GUITickBox(createFilterRectT(), text)
|
||||
{
|
||||
UserData = text,
|
||||
Selected = defaultState,
|
||||
@@ -450,6 +453,109 @@ namespace Barotrauma
|
||||
filterEmpty = addTickBox("FilterEmptyServers".ToIdentifier());
|
||||
filterOffensive = addTickBox("FilterOffensiveServers".ToIdentifier());
|
||||
|
||||
// Language filter
|
||||
if (ServerLanguageOptions.Options.Any())
|
||||
{
|
||||
var languageKey = "Language".ToIdentifier();
|
||||
var allLanguagesKey = "AllLanguages".ToIdentifier();
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), filters.Content.RectTransform), TextManager.Get(languageKey), font: GUIStyle.SubHeadingFont)
|
||||
{
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
languageDropdown = new GUIDropDown(createFilterRectT(), selectMultiple: true);
|
||||
|
||||
languageDropdown.AddItem(TextManager.Get(allLanguagesKey), allLanguagesKey);
|
||||
var allTickbox = languageDropdown.ListBox.Content.FindChild(allLanguagesKey)?.GetChild<GUITickBox>();
|
||||
|
||||
// Spacer between "All" and the individual languages
|
||||
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.0f), languageDropdown.ListBox.Content.RectTransform)
|
||||
{
|
||||
MinSize = new Point(0, GUI.IntScaleCeiling(2))
|
||||
}, style: null)
|
||||
{
|
||||
Color = Color.DarkGray,
|
||||
CanBeFocused = false
|
||||
};
|
||||
|
||||
var selectedLanguages
|
||||
= ServerListFilters.Instance.GetAttributeLanguageIdentifierArray(
|
||||
languageKey,
|
||||
Array.Empty<LanguageIdentifier>());
|
||||
foreach (var (label, identifier, _) in ServerLanguageOptions.Options)
|
||||
{
|
||||
languageDropdown.AddItem(label, identifier);
|
||||
}
|
||||
|
||||
if (!selectedLanguages.Any())
|
||||
{
|
||||
selectedLanguages = ServerLanguageOptions.Options.Select(o => o.Identifier).ToArray();
|
||||
}
|
||||
|
||||
foreach (var lang in selectedLanguages)
|
||||
{
|
||||
languageDropdown.SelectItem(lang);
|
||||
}
|
||||
|
||||
if (ServerLanguageOptions.Options.All(o => selectedLanguages.Any(l => o.Identifier == l)))
|
||||
{
|
||||
languageDropdown.SelectItem(allLanguagesKey);
|
||||
languageDropdown.Text = TextManager.Get(allLanguagesKey);
|
||||
}
|
||||
|
||||
var langTickboxes = languageDropdown.ListBox.Content.Children
|
||||
.Where(c => c.UserData is LanguageIdentifier)
|
||||
.Select(c => c.GetChild<GUITickBox>())
|
||||
.ToArray();
|
||||
|
||||
bool inSelectedCall = false;
|
||||
languageDropdown.OnSelected = (_, userData) =>
|
||||
{
|
||||
if (inSelectedCall) { return true; }
|
||||
try
|
||||
{
|
||||
inSelectedCall = true;
|
||||
|
||||
if (Equals(allLanguagesKey, userData))
|
||||
{
|
||||
foreach (var tb in langTickboxes)
|
||||
{
|
||||
tb.Selected = allTickbox.Selected;
|
||||
}
|
||||
}
|
||||
|
||||
bool noneSelected = langTickboxes.All(tb => !tb.Selected);
|
||||
bool allSelected = langTickboxes.All(tb => tb.Selected);
|
||||
|
||||
if (allSelected != allTickbox.Selected)
|
||||
{
|
||||
allTickbox.Selected = allSelected;
|
||||
}
|
||||
|
||||
if (allSelected)
|
||||
{
|
||||
languageDropdown.Text = TextManager.Get(allLanguagesKey);
|
||||
}
|
||||
else if (noneSelected)
|
||||
{
|
||||
languageDropdown.Text = TextManager.Get("None");
|
||||
}
|
||||
|
||||
var languages = languageDropdown.SelectedDataMultiple.OfType<LanguageIdentifier>();
|
||||
|
||||
ServerListFilters.Instance.SetAttribute(languageKey, string.Join(", ", languages));
|
||||
GameSettings.SaveCurrentConfig();
|
||||
return true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
inSelectedCall = false;
|
||||
FilterServers();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Filter Tags
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.05f), filters.Content.RectTransform), TextManager.Get("servertags"), font: GUIStyle.SubHeadingFont)
|
||||
{
|
||||
@@ -713,7 +819,7 @@ namespace Barotrauma
|
||||
|
||||
private void SortList(ColumnLabel sortBy, bool toggle)
|
||||
{
|
||||
if (!(labelHolder.GetChildByUserData(sortBy) is GUIButton button)) { return; }
|
||||
if (labelHolder.GetChildByUserData(sortBy) is not GUIButton button) { return; }
|
||||
|
||||
sortedBy = sortBy;
|
||||
|
||||
@@ -730,51 +836,74 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
bool ascending = arrowUp.Visible;
|
||||
sortedAscending = arrowUp.Visible;
|
||||
if (toggle)
|
||||
{
|
||||
ascending = !ascending;
|
||||
sortedAscending = !sortedAscending;
|
||||
}
|
||||
|
||||
arrowUp.Visible = ascending;
|
||||
arrowDown.Visible = !ascending;
|
||||
arrowUp.Visible = sortedAscending;
|
||||
arrowDown.Visible = !sortedAscending;
|
||||
serverList.Content.RectTransform.SortChildren((c1, c2) =>
|
||||
{
|
||||
if (!(c1.GUIComponent.UserData is ServerInfo s1)) { return 0; }
|
||||
if (!(c2.GUIComponent.UserData is ServerInfo s2)) { return 0; }
|
||||
|
||||
switch (sortBy)
|
||||
{
|
||||
case ColumnLabel.ServerListCompatible:
|
||||
bool s1Compatible = NetworkMember.IsCompatible(GameMain.Version, s1.GameVersion);
|
||||
bool s2Compatible = NetworkMember.IsCompatible(GameMain.Version, s2.GameVersion);
|
||||
|
||||
if (s1Compatible == s2Compatible) { return 0; }
|
||||
return (s1Compatible ? 1 : -1) * (ascending ? 1 : -1);
|
||||
case ColumnLabel.ServerListHasPassword:
|
||||
if (s1.HasPassword == s2.HasPassword) { return 0; }
|
||||
return (s1.HasPassword ? 1 : -1) * (ascending ? 1 : -1);
|
||||
case ColumnLabel.ServerListName:
|
||||
// I think we actually want culture-specific sorting here?
|
||||
return string.Compare(s1.ServerName, s2.ServerName, StringComparison.CurrentCulture) * (ascending ? 1 : -1);
|
||||
case ColumnLabel.ServerListRoundStarted:
|
||||
if (s1.GameStarted == s2.GameStarted) { return 0; }
|
||||
return (s1.GameStarted ? 1 : -1) * (ascending ? 1 : -1);
|
||||
case ColumnLabel.ServerListPlayers:
|
||||
return s2.PlayerCount.CompareTo(s1.PlayerCount) * (ascending ? 1 : -1);
|
||||
case ColumnLabel.ServerListPing:
|
||||
return (s1.Ping.TryUnwrap(out var s1Ping), s2.Ping.TryUnwrap(out var s2Ping)) switch
|
||||
{
|
||||
(false, false) => 0,
|
||||
(true, true) => s2Ping.CompareTo(s1Ping) * (ascending ? 1 : -1),
|
||||
(false, true) => 1,
|
||||
(true, false) => -1
|
||||
};
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
if (c1.GUIComponent.UserData is not ServerInfo s1) { return 0; }
|
||||
if (c2.GUIComponent.UserData is not ServerInfo s2) { return 0; }
|
||||
int comparison = sortedAscending ? 1 : -1;
|
||||
return CompareServer(sortBy, s1, s2) * comparison;
|
||||
});
|
||||
}
|
||||
|
||||
private void InsertServer(ServerInfo serverInfo, GUIComponent component)
|
||||
{
|
||||
var children = serverList.Content.RectTransform.Children.Reverse().ToList();
|
||||
|
||||
int comparison = sortedAscending ? 1 : -1;
|
||||
foreach (var child in children)
|
||||
{
|
||||
if (child.GUIComponent.UserData is not ServerInfo serverInfo2 || serverInfo.Equals(serverInfo2)) { continue; }
|
||||
if (CompareServer(sortedBy, serverInfo, serverInfo2) * comparison >= 0)
|
||||
{
|
||||
var index = serverList.Content.RectTransform.GetChildIndex(child);
|
||||
component.RectTransform.RepositionChildInHierarchy(index + 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
component.RectTransform.SetAsFirstChild();
|
||||
}
|
||||
|
||||
private static int CompareServer(ColumnLabel sortBy, ServerInfo s1, ServerInfo s2)
|
||||
{
|
||||
switch (sortBy)
|
||||
{
|
||||
case ColumnLabel.ServerListCompatible:
|
||||
bool s1Compatible = NetworkMember.IsCompatible(GameMain.Version, s1.GameVersion);
|
||||
bool s2Compatible = NetworkMember.IsCompatible(GameMain.Version, s2.GameVersion);
|
||||
|
||||
if (s1Compatible == s2Compatible) { return 0; }
|
||||
return s1Compatible ? -1 : 1;
|
||||
case ColumnLabel.ServerListHasPassword:
|
||||
if (s1.HasPassword == s2.HasPassword) { return 0; }
|
||||
return s1.HasPassword ? 1 : -1;
|
||||
case ColumnLabel.ServerListName:
|
||||
// I think we actually want culture-specific sorting here?
|
||||
return string.Compare(s1.ServerName, s2.ServerName, StringComparison.CurrentCulture);
|
||||
case ColumnLabel.ServerListRoundStarted:
|
||||
if (s1.GameStarted == s2.GameStarted) { return 0; }
|
||||
return s1.GameStarted ? 1 : -1;
|
||||
case ColumnLabel.ServerListPlayers:
|
||||
return s2.PlayerCount.CompareTo(s1.PlayerCount);
|
||||
case ColumnLabel.ServerListPing:
|
||||
return (s1.Ping.TryUnwrap(out var s1Ping), s2.Ping.TryUnwrap(out var s2Ping)) switch
|
||||
{
|
||||
(false, false) => 0,
|
||||
(true, true) => s2Ping.CompareTo(s1Ping),
|
||||
(false, true) => 1,
|
||||
(true, false) => -1
|
||||
};
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Select()
|
||||
{
|
||||
@@ -821,6 +950,7 @@ namespace Barotrauma
|
||||
|
||||
UpdateFriendsList();
|
||||
panelAnimator?.Update();
|
||||
|
||||
scanServersButton.Enabled = (DateTime.Now - lastRefreshTime) >= AllowedRefreshInterval;
|
||||
|
||||
if (PlayerInput.PrimaryMouseButtonClicked())
|
||||
@@ -840,7 +970,7 @@ namespace Barotrauma
|
||||
RemoveMsgFromServerList(MsgUserData.NoMatchingServers);
|
||||
foreach (GUIComponent child in serverList.Content.Children)
|
||||
{
|
||||
if (!(child.UserData is ServerInfo serverInfo)) { continue; }
|
||||
if (child.UserData is not ServerInfo serverInfo) { continue; }
|
||||
child.Visible = ShouldShowServer(serverInfo);
|
||||
}
|
||||
|
||||
@@ -851,6 +981,20 @@ namespace Barotrauma
|
||||
serverList.UpdateScrollBarSize();
|
||||
}
|
||||
|
||||
private bool AllLanguagesVisible
|
||||
{
|
||||
get
|
||||
{
|
||||
if (languageDropdown is null) { return true; }
|
||||
|
||||
// CountChildren-1 because there's a separator element in there that can't be selected
|
||||
int tickBoxCount = languageDropdown.ListBox.Content.CountChildren - 1;
|
||||
int selectedCount = languageDropdown.SelectedIndexMultiple.Count();
|
||||
|
||||
return selectedCount >= tickBoxCount;
|
||||
}
|
||||
}
|
||||
|
||||
private bool ShouldShowServer(ServerInfo serverInfo)
|
||||
{
|
||||
#if !DEBUG
|
||||
@@ -918,6 +1062,14 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
if (!AllLanguagesVisible)
|
||||
{
|
||||
if (!languageDropdown.SelectedDataMultiple.OfType<LanguageIdentifier>().Contains(serverInfo.Language))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (GUITickBox tickBox in gameModeTickBoxes.Values)
|
||||
{
|
||||
var gameMode = (Identifier)tickBox.UserData;
|
||||
@@ -1031,8 +1183,8 @@ namespace Barotrauma
|
||||
if (!(userdata is FriendInfo { IsInServer: true } info)) { return false; }
|
||||
|
||||
if (info.IsInServer
|
||||
&& info.ConnectCommand is Some<ConnectCommand> { Value: { EndpointOrLobby: var endpointOrLobby } }
|
||||
&& endpointOrLobby.TryGet(out ConnectCommand.NameAndEndpoint nameAndEndpoint))
|
||||
&& info.ConnectCommand.TryUnwrap(out var command)
|
||||
&& command.EndpointOrLobby.TryGet(out ConnectCommand.NameAndEndpoint nameAndEndpoint))
|
||||
{
|
||||
const int framePadding = 5;
|
||||
|
||||
@@ -1270,7 +1422,7 @@ namespace Barotrauma
|
||||
serverPreview.Content.ClearChildren();
|
||||
panelAnimator.RightEnabled = false;
|
||||
joinButton.Enabled = false;
|
||||
selectedServer = null;
|
||||
selectedServer = Option.None;
|
||||
|
||||
if (selectedTab == TabEnum.All)
|
||||
{
|
||||
@@ -1370,8 +1522,7 @@ namespace Barotrauma
|
||||
UpdateServerInfoUI(serverInfo);
|
||||
if (!skipPing) { PingUtils.GetServerPing(serverInfo, UpdateServerInfoUI); }
|
||||
|
||||
SortList(sortedBy, toggle: false);
|
||||
FilterServers();
|
||||
InsertServer(serverInfo, serverFrame);
|
||||
}
|
||||
|
||||
private void UpdateServerInfoUI(ServerInfo serverInfo)
|
||||
@@ -1629,7 +1780,7 @@ namespace Barotrauma
|
||||
#endif
|
||||
}
|
||||
|
||||
private Color GetPingTextColor(int ping)
|
||||
private static Color GetPingTextColor(int ping)
|
||||
{
|
||||
if (ping < 0) { return Color.DarkRed; }
|
||||
return ToolBox.GradientLerp(ping / 200.0f, GUIStyle.Green, GUIStyle.Orange, GUIStyle.Red);
|
||||
@@ -1640,12 +1791,10 @@ namespace Barotrauma
|
||||
graphics.Clear(Color.CornflowerBlue);
|
||||
|
||||
GameMain.TitleScreen.DrawLoadingText = false;
|
||||
GameMain.MainMenuScreen.DrawBackground(graphics, spriteBatch);
|
||||
|
||||
spriteBatch.Begin(SpriteSortMode.Deferred, null, GUI.SamplerState, null, GameMain.ScissorTestEnable);
|
||||
|
||||
GameMain.MainMenuScreen.DrawBackground(graphics, spriteBatch);
|
||||
GUI.Draw(Cam, spriteBatch);
|
||||
|
||||
spriteBatch.End();
|
||||
}
|
||||
|
||||
@@ -1666,6 +1815,7 @@ namespace Barotrauma
|
||||
{
|
||||
ServerListFilters.Instance.SetAttribute(ternaryFilter.Key, ternaryFilter.Value.SelectedData.ToString());
|
||||
}
|
||||
GameSettings.SaveCurrentConfig();
|
||||
}
|
||||
|
||||
public void LoadServerFilters()
|
||||
|
||||
Reference in New Issue
Block a user