Unstable v0.19.1.0

This commit is contained in:
Juan Pablo Arce
2022-08-19 13:59:08 -03:00
parent 6b55adcdd9
commit 1219615d64
192 changed files with 3875 additions and 2648 deletions
@@ -810,7 +810,7 @@ namespace Barotrauma
GUI.DrawString(spriteBatch, pos, interestingPos.PositionType.ToString(), Color.White, font: GUIStyle.LargeFont);
}
// TODO: Improve this temporary level editor debug solution (or remove it)
// TODO: Improve this temporary level editor debug solution
foreach (var pathPoint in Level.Loaded.PathPoints)
{
Vector2 pathPointPos = new Vector2(pathPoint.Position.X, -pathPoint.Position.Y);
@@ -833,6 +833,17 @@ namespace Barotrauma
GUI.DrawString(spriteBatch, pathPointPos, "Path Point\n" + pathPoint.Id, color, font: GUIStyle.LargeFont);
}
foreach (var location in Level.Loaded.AbyssResources)
{
if (location.Resources == null) { continue; }
foreach (var resource in location.Resources)
{
Vector2 resourcePos = new Vector2(resource.Position.X, -resource.Position.Y);
spriteBatch.DrawCircle(resourcePos, 100, 6, Color.DarkGreen * 0.5f, thickness: (int)(2 / Cam.Zoom));
GUI.DrawString(spriteBatch, resourcePos, resource.Name, Color.DarkGreen, font: GUIStyle.LargeFont);
}
}
/*for (int i = 0; i < Level.Loaded.distanceField.Count; i++)
{
GUI.DrawRectangle(spriteBatch,
@@ -390,7 +390,7 @@ namespace Barotrauma
SelectTab(tb, userdata);
GameMain.Client = new GameClient(MultiplayerPreferences.Instance.PlayerName.FallbackNullOrEmpty(SteamManager.GetUsername()),
IPAddress.Loopback.ToString(), 0, "localhost", 0, false);
new LidgrenEndpoint(IPAddress.Loopback, NetConfig.DefaultPort), "localhost", Option<int>.None());
return true;
}
@@ -489,7 +489,7 @@ namespace Barotrauma
if (GameMain.Client != null)
{
GameMain.Client.Disconnect();
GameMain.Client.Quit();
GameMain.Client = null;
}
@@ -834,9 +834,9 @@ namespace Barotrauma
arguments += " -nopassword";
}
if (Steam.SteamManager.GetSteamID() != 0)
if (SteamManager.GetSteamId().TryUnwrap(out var steamId1))
{
arguments += " -steamid " + Steam.SteamManager.GetSteamID();
arguments += " -steamid " + steamId1.Value;
}
int ownerKey = Math.Max(CryptoRandom.Instance.Next(), 1);
arguments += " -ownerkey " + ownerKey;
@@ -865,8 +865,12 @@ namespace Barotrauma
Thread.Sleep(1000); //wait until the server is ready before connecting
GameMain.Client = new GameClient(MultiplayerPreferences.Instance.PlayerName.FallbackNullOrEmpty(
SteamManager.GetUsername().FallbackNullOrEmpty(name)),
System.Net.IPAddress.Loopback.ToString(), Steam.SteamManager.GetSteamID(), name, ownerKey, true);
SteamManager.GetUsername().FallbackNullOrEmpty(name)),
SteamManager.GetSteamId().TryUnwrap(out var steamId)
? new SteamP2PEndpoint(steamId)
: (Endpoint)new LidgrenEndpoint(IPAddress.Loopback, NetConfig.DefaultPort),
name,
Option<int>.Some(ownerKey));
}
catch (Exception e)
{
@@ -68,12 +68,28 @@ namespace Barotrauma
{
OnClicked = (guiButton, o) =>
{
GameMain.Client?.Disconnect();
GameMain.Client?.Quit();
GameMain.MainMenuScreen.Select();
return false;
}
};
if (!GameMain.Client.IsServerOwner)
{
if (GameMain.Client.ClientPeer.ServerContentPackages.Length == 0)
{
string errorMsg = $"Error in ModDownloadScreen: the list of mods the server has enabled was empty. Content package list received: {GameMain.Client.ClientPeer.ContentPackageOrderReceived}";
GameAnalyticsManager.AddErrorEventOnce("ModDownloadScreen.Select:NoContentPackages", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
throw new InvalidOperationException(errorMsg);
}
if (GameMain.Client.ClientPeer.ServerContentPackages.None(p => p.CorePackage != null))
{
string errorMsg = $"Error in ModDownloadScreen: no core packages in the list of mods the server has enabled. Content package list received: {GameMain.Client.ClientPeer.ContentPackageOrderReceived}";
GameAnalyticsManager.AddErrorEventOnce("ModDownloadScreen.Select:NoCorePackage", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
throw new InvalidOperationException(errorMsg);
}
}
var missingPackages = GameMain.Client.ClientPeer.ServerContentPackages
.Where(sp => sp.ContentPackage is null).ToArray();
if (!missingPackages.Any())
@@ -84,11 +100,14 @@ namespace Barotrauma
ContentPackageManager.EnabledPackages.SetCore(
GameMain.Client.ClientPeer.ServerContentPackages
.Select(p => p.CorePackage)
.First(p => p != null));
ContentPackageManager.EnabledPackages.SetRegular(
.OfType<CorePackage>().First());
List<RegularPackage> regularPackages =
GameMain.Client.ClientPeer.ServerContentPackages
.Select(p => p.RegularPackage)
.Where(p => p != null).ToArray());
.OfType<RegularPackage>().ToList();
//keep enabled client-side-only mods enabled
regularPackages.AddRange(ContentPackageManager.EnabledPackages.Regular.Where(p => !p.HasMultiplayerSyncedContent));
ContentPackageManager.EnabledPackages.SetRegular(regularPackages);
}
GameMain.NetLobbyScreen.Select();
return;
@@ -153,7 +172,7 @@ namespace Barotrauma
buttonContainerSpacing(0.2f);
button(TextManager.Get("No"), () =>
{
GameMain.Client?.Disconnect();
GameMain.Client?.Quit();
GameMain.MainMenuScreen.Select();
});
buttonContainerSpacing(0.1f);
@@ -173,10 +192,10 @@ namespace Barotrauma
if (GameMain.Client != null)
{
BulkDownloader.SubscribeToServerMods(missingIds,
rejoinEndpoint: GameMain.Client.ClientPeer.ServerConnection.EndPointString,
rejoinLobby: SteamManager.CurrentLobbyID,
rejoinServerName: GameMain.NetLobbyScreen.ServerName.Text);
GameMain.Client.Disconnect();
new ConnectCommand(
serverName: GameMain.Client.ServerName,
endpoint: GameMain.Client.ClientPeer.ServerEndpoint));
GameMain.Client.Quit();
}
GameMain.MainMenuScreen.Select();
}, width: 0.7f);
@@ -275,19 +294,22 @@ namespace Barotrauma
?? serverPackages.FirstOrDefault(p => p.CorePackage != null)
?.CorePackage
?? throw new Exception($"Failed to find core package to enable");
RegularPackage[] regularPackages
List<RegularPackage> regularPackages
= serverPackages.Where(p => p.CorePackage is null)
.Select(p =>
p.RegularPackage
?? downloadedPackages.FirstOrDefault(d => d is RegularPackage && d.Hash.Equals(p.Hash))
?? throw new Exception($"Could not find regular package \"{p.Name}\""))
.Cast<RegularPackage>()
.ToArray();
.ToList();
foreach (var regularPackage in regularPackages)
{
DebugConsole.NewMessage($"Enabling \"{regularPackage.Name}\" ({regularPackage.Dir})", Color.Lime);
}
//keep enabled client-side-only mods enabled
regularPackages.AddRange(ContentPackageManager.EnabledPackages.Regular.Where(p => !p.HasMultiplayerSyncedContent));
ContentPackageManager.EnabledPackages.BackUp();
ContentPackageManager.EnabledPackages.SetCore(corePackage);
ContentPackageManager.EnabledPackages.SetRegular(regularPackages);
@@ -1529,14 +1529,13 @@ namespace Barotrauma
while (i < MultiplayerPreferences.Instance.JobPreferences.Count)
{
var jobPreference = MultiplayerPreferences.Instance.JobPreferences[i];
if (!JobPrefab.Prefabs.ContainsKey(jobPreference.JobIdentifier))
if (!JobPrefab.Prefabs.TryGet(jobPreference.JobIdentifier, out JobPrefab prefab) || prefab.HiddenJob)
{
MultiplayerPreferences.Instance.JobPreferences.RemoveAt(i);
continue;
}
// The old job variant system used one-based indexing
// so let's make sure no one get to pick a variant which doesn't exist
var prefab = JobPrefab.Prefabs[jobPreference.JobIdentifier];
var variant = Math.Min(jobPreference.Variant, prefab.Variants - 1);
jobPrefab = new JobVariant(prefab, variant);
break;
@@ -2160,15 +2159,8 @@ namespace Barotrauma
if (child != null) { PlayerList.RemoveChild(child); }
}
private Client ExtractClientFromClickableArea(GUITextBlock.ClickableArea area)
{
if (!UInt64.TryParse(area.Data.Metadata, out UInt64 id)) { return null; }
Client client = GameMain.Client.ConnectedClients.Find(c => c.SteamID == id)
?? GameMain.Client.ConnectedClients.Find(c => c.ID == id)
?? GameMain.Client.PreviouslyConnectedClients.FirstOrDefault(c => c.SteamID == id)
?? GameMain.Client.PreviouslyConnectedClients.FirstOrDefault(c => c.ID == id);
return client;
}
public static Client ExtractClientFromClickableArea(GUITextBlock.ClickableArea area)
=> area.Data.ExtractClient();
public void SelectPlayer(GUITextBlock component, GUITextBlock.ClickableArea area)
{
@@ -2188,29 +2180,35 @@ namespace Barotrauma
public static void CreateModerationContextMenu(Client client)
{
if (GUIContextMenu.CurrentContextMenu != null) { return; }
if (GameMain.IsSingleplayer || client == null || ((!GameMain.Client?.PreviouslyConnectedClients?.Contains(client)) ?? true)) { return; }
bool hasSteam = client.SteamID > 0 && SteamManager.IsInitialized,
canKick = GameMain.Client.HasPermission(ClientPermissions.Kick),
canBan = GameMain.Client.HasPermission(ClientPermissions.Ban) && client.AllowKicking,
canPromo = GameMain.Client.HasPermission(ClientPermissions.ManagePermissions);
if (GameMain.IsSingleplayer || client == null) { return; }
if (!(GameMain.Client is { PreviouslyConnectedClients: var previouslyConnectedClients })
|| !previouslyConnectedClients.Contains(client)) { return; }
bool hasAccountId = client.AccountId.IsSome();
bool canKick = GameMain.Client.HasPermission(ClientPermissions.Kick);
bool canBan = GameMain.Client.HasPermission(ClientPermissions.Ban) && client.AllowKicking;
bool canManagePermissions = GameMain.Client.HasPermission(ClientPermissions.ManagePermissions);
// Disable options if we are targeting ourselves
if (client.ID == GameMain.Client?.ID)
if (client.SessionId == GameMain.Client.SessionId)
{
canKick = canBan = canPromo = false;
canKick = canBan = canManagePermissions = false;
}
List<ContextMenuOption> options = new List<ContextMenuOption>
List<ContextMenuOption> options = new List<ContextMenuOption>();
if (client.AccountId.TryUnwrap(out var accountId) && accountId is SteamId steamId)
{
new ContextMenuOption("ViewSteamProfile", isEnabled: hasSteam, onSelected: delegate
{
Steamworks.SteamFriends.OpenWebOverlay($"https://steamcommunity.com/profiles/{client.SteamID}");
}),
new ContextMenuOption("ModerationMenu.ManagePlayer", isEnabled: true, onSelected: delegate
options.Add(new ContextMenuOption("ViewSteamProfile", isEnabled: hasAccountId, onSelected: () =>
{
SteamManager.OverlayProfile(steamId);
}));
}
options.Add(new ContextMenuOption("ModerationMenu.ManagePlayer", isEnabled: true, onSelected: () =>
{
GameMain.NetLobbyScreen?.SelectPlayer(client);
})
};
}));
// Creates sub context menu options for all the ranks
List<ContextMenuOption> rankOptions = new List<ContextMenuOption>();
@@ -2236,18 +2234,18 @@ namespace Barotrauma
}) { Tooltip = rank.Description });
}
options.Add(new ContextMenuOption("Rank", isEnabled: canPromo, options: rankOptions.ToArray()));
options.Add(new ContextMenuOption("Rank", isEnabled: canManagePermissions, options: rankOptions.ToArray()));
Color clientColor = client.Character?.Info?.Job.Prefab.UIColor ?? Color.White;
if (GameMain.Client.ConnectedClients.Contains(client))
{
options.Add(new ContextMenuOption(client.MutedLocally ? "Unmute" : "Mute", isEnabled: client.ID != GameMain.Client?.ID, onSelected: delegate
options.Add(new ContextMenuOption(client.MutedLocally ? "Unmute" : "Mute", isEnabled: client.SessionId != GameMain.Client.SessionId, onSelected: delegate
{
client.MutedLocally = !client.MutedLocally;
}));
bool kickEnabled = client.ID != GameMain.Client?.ID && client.AllowKicking;
bool kickEnabled = client.SessionId != GameMain.Client.SessionId && client.AllowKicking;
// if the user can kick create a kick option else create the votekick option
ContextMenuOption kickOption;
@@ -2281,7 +2279,7 @@ namespace Barotrauma
public bool SelectPlayer(Client selectedClient)
{
bool myClient = selectedClient.ID == GameMain.Client.ID;
bool myClient = selectedClient.SessionId == GameMain.Client.SessionId;
bool hasManagePermissions = GameMain.Client.HasPermission(ClientPermissions.ManagePermissions);
PlayerFrame = new GUIButton(new RectTransform(Vector2.One, GUI.Canvas, Anchor.Center), style: null)
@@ -2510,14 +2508,6 @@ namespace Barotrauma
};
banButton.OnClicked = (bt, userdata) => { BanPlayer(selectedClient); return true; };
banButton.OnClicked += ClosePlayerFrame;
var rangebanButton = new GUIButton(new RectTransform(new Vector2(0.34f, 1.0f), buttonAreaTop.RectTransform),
TextManager.Get("BanRange"))
{
UserData = selectedClient
};
rangebanButton.OnClicked = (bt, userdata) => { BanPlayerRange(selectedClient); return true; };
rangebanButton.OnClicked += ClosePlayerFrame;
}
if (GameMain.Client != null && GameMain.Client.ConnectedClients.Contains(selectedClient))
@@ -2528,7 +2518,7 @@ namespace Barotrauma
var kickVoteButton = new GUIButton(new RectTransform(new Vector2(0.34f, 1.0f), buttonAreaLower.RectTransform),
TextManager.Get("VoteToKick"))
{
Enabled = !selectedClient.HasKickVoteFromID(GameMain.Client.ID),
Enabled = !selectedClient.HasKickVoteFromSessionId(GameMain.Client.SessionId),
OnClicked = (btn, userdata) => { GameMain.Client.VoteForKick(selectedClient); btn.Enabled = false; return true; },
UserData = selectedClient
};
@@ -2560,7 +2550,7 @@ namespace Barotrauma
}
}
if (selectedClient.SteamID != 0 && Steam.SteamManager.IsInitialized)
if (selectedClient.AccountId.TryUnwrap(out var accountId) && accountId is SteamId steamId && Steam.SteamManager.IsInitialized)
{
var viewSteamProfileButton = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), headerContainer.RectTransform, Anchor.TopCenter) { MaxSize = new Point(int.MaxValue, (int)(40 * GUI.Scale)) },
TextManager.Get("ViewSteamProfile"))
@@ -2570,7 +2560,7 @@ namespace Barotrauma
viewSteamProfileButton.TextBlock.AutoScaleHorizontal = true;
viewSteamProfileButton.OnClicked = (bt, userdata) =>
{
SteamManager.OverlayCustomURL("https://steamcommunity.com/profiles/" + selectedClient.SteamID.ToString());
SteamManager.OverlayProfile(steamId);
return true;
};
}
@@ -2628,13 +2618,7 @@ namespace Barotrauma
public void BanPlayer(Client client)
{
if (GameMain.NetworkMember == null || client == null) { return; }
GameMain.Client.CreateKickReasonPrompt(client.Name, ban: true, rangeBan: false);
}
public void BanPlayerRange(Client client)
{
if (GameMain.NetworkMember == null || client == null) { return; }
GameMain.Client.CreateKickReasonPrompt(client.Name, ban: true, rangeBan: true);
GameMain.Client.CreateKickReasonPrompt(client.Name, ban: true);
}
public override void AddToGUIUpdateList()
@@ -2679,7 +2663,7 @@ namespace Barotrauma
if (child.FindChild(c => c.UserData is Pair<string, float> pair && pair.First == "soundicon") is GUIImage soundIcon)
{
double voipAmplitude = 0.0f;
if (client.ID != GameMain.Client.ID)
if (client.SessionId != GameMain.Client.SessionId)
{
voipAmplitude = client.VoipSound?.CurrentAmplitude ?? 0.0f;
}
@@ -53,21 +53,19 @@ namespace Barotrauma
private class FriendInfo
{
public UInt64 SteamID;
public UInt64 SteamId;
public string Name;
public Sprite Sprite;
public LocalizedString StatusText;
public bool PlayingThisGame;
public bool PlayingAnotherGame;
public string ConnectName;
public string ConnectEndpoint;
public UInt64 ConnectLobby;
public Option<ConnectCommand> ConnectCommand = Option<ConnectCommand>.None();
public bool InServer
{
get
{
return PlayingThisGame && !StatusText.IsNullOrWhiteSpace() && (!string.IsNullOrWhiteSpace(ConnectEndpoint) || ConnectLobby != 0);
return PlayingThisGame && !StatusText.IsNullOrWhiteSpace() && ConnectCommand.IsSome();
}
}
}
@@ -81,7 +79,7 @@ namespace Barotrauma
private List<ServerInfo> favoriteServers;
private List<ServerInfo> recentServers;
private readonly Dictionary<string, int> activePings = new Dictionary<string, int>();
private readonly Dictionary<IPAddress, int> activePings = new Dictionary<IPAddress, int>();
private enum ServerListTab
{
@@ -153,7 +151,6 @@ namespace Barotrauma
private GUITickBox filterIncompatible;
private GUITickBox filterFull;
private GUITickBox filterEmpty;
private GUITickBox filterWhitelisted;
private Dictionary<Identifier, GUIDropDown> ternaryFilters;
private Dictionary<Identifier, GUITickBox> filterTickBoxes;
private Dictionary<Identifier, GUITickBox> playStyleTickBoxes;
@@ -405,7 +402,6 @@ namespace Barotrauma
filterIncompatible = addTickBox("FilterIncompatibleServers".ToIdentifier());
filterFull = addTickBox("FilterFullServers".ToIdentifier());
filterEmpty = addTickBox("FilterEmptyServers".ToIdentifier());
filterWhitelisted = addTickBox("FilterWhitelistedServers".ToIdentifier());
filterOffensive = addTickBox("FilterOffensiveServers".ToIdentifier());
// Filter Tags
@@ -608,14 +604,14 @@ namespace Barotrauma
{
if (selectedServer != null)
{
if (!string.IsNullOrWhiteSpace(selectedServer.IP) && !string.IsNullOrWhiteSpace(selectedServer.Port) && int.TryParse(selectedServer.Port, out _))
{
JoinServer(selectedServer.IP + ":" + selectedServer.Port, selectedServer.ServerName);
}
else if (selectedServer.LobbyID != 0)
if (selectedServer.LobbyID != 0)
{
Steam.SteamManager.JoinLobby(selectedServer.LobbyID, true);
}
else if (selectedServer.Endpoint != null)
{
JoinServer(selectedServer.Endpoint, selectedServer.ServerName);
}
else
{
new GUIMessageBox("", TextManager.Get("ServerOffline"));
@@ -753,20 +749,11 @@ namespace Barotrauma
doc.SaveSafe(file);
}
public ServerInfo UpdateServerInfoWithServerSettings(NetworkConnection endpoint, ServerSettings serverSettings)
public ServerInfo UpdateServerInfoWithServerSettings(NetworkConnection connection, ServerSettings serverSettings)
{
UInt64 steamId = 0;
string ip = ""; string port = "";
if (endpoint is SteamP2PConnection steamP2PConnection) { steamId = steamP2PConnection.SteamID; }
else if (endpoint is LidgrenConnection lidgrenConnection)
{
ip = lidgrenConnection.IPString;
port = lidgrenConnection.Port.ToString();
}
bool isInfoNew = false;
ServerInfo info = serverList.Content.FindChild(d => (d.UserData is ServerInfo serverInfo) &&
(steamId != 0 ? steamId == serverInfo.OwnerID : (ip == serverInfo.IP && port == serverInfo.Port)))?.UserData as ServerInfo;
serverInfo.Endpoint == connection.Endpoint)?.UserData as ServerInfo;
if (info == null)
{
isInfoNew = true;
@@ -775,17 +762,14 @@ namespace Barotrauma
info.ServerName = serverSettings.ServerName;
info.ServerMessage = serverSettings.ServerMessageText;
info.OwnerID = steamId;
info.Endpoint = connection.Endpoint;
info.LobbyID = SteamManager.CurrentLobbyID;
info.IP = ip;
info.Port = port;
info.GameMode = GameMain.NetLobbyScreen.SelectedMode?.Identifier ?? Identifier.Empty;
info.GameStarted = Screen.Selected != GameMain.NetLobbyScreen;
info.GameVersion = GameMain.Version.ToString();
info.MaxPlayers = serverSettings.MaxPlayers;
info.PlayStyle = serverSettings.PlayStyle;
info.RespondedToSteamQuery = true;
info.UsingWhiteList = serverSettings.Whitelist.Enabled;
info.TraitorsEnabled = serverSettings.TraitorsEnabled;
info.SubSelectionMode = serverSettings.SubSelectionMode;
info.ModeSelectionMode = serverSettings.ModeSelectionMode;
@@ -807,10 +791,9 @@ namespace Barotrauma
public void AddToRecentServers(ServerInfo info)
{
if (!string.IsNullOrEmpty(info.IP))
if (info.Endpoint is LidgrenEndpoint { NetEndpoint: { Address: var ip } } && IPAddress.IsLoopback(ip))
{
//don't add localhost to recent servers
if (IPAddress.TryParse(info.IP, out IPAddress ip) && IPAddress.IsLoopback(ip)) { return; }
return;
}
info.Recent = true;
@@ -870,8 +853,7 @@ namespace Barotrauma
private void SortList(string sortBy, bool toggle)
{
GUIButton button = labelHolder.GetChildByUserData(sortBy) as GUIButton;
if (button == null) { return; }
if (!(labelHolder.GetChildByUserData(sortBy) is GUIButton button)) { return; }
sortedBy = sortBy;
@@ -985,7 +967,7 @@ namespace Barotrauma
if (GameMain.Client != null)
{
GameMain.Client.Disconnect();
GameMain.Client.Quit();
GameMain.Client = null;
}
@@ -1060,14 +1042,13 @@ namespace Barotrauma
(!filterIncompatible.Selected || !incompatible) &&
(!filterFull.Selected || serverInfo.PlayerCount < serverInfo.MaxPlayers) &&
(!filterEmpty.Selected || serverInfo.PlayerCount > 0) &&
(!filterWhitelisted.Selected || serverInfo.UsingWhiteList == true) &&
(!filterOffensive.Selected || !ForbiddenWordFilter.IsForbidden(serverInfo.ServerName)) &&
karmaFilterPassed &&
friendlyFireFilterPassed &&
traitorsFilterPassed &&
voipFilterPassed &&
moddedFilterPassed &&
((selectedTab == ServerListTab.All && (serverInfo.LobbyID != 0 || !string.IsNullOrWhiteSpace(serverInfo.Port))) ||
((selectedTab == ServerListTab.All && (serverInfo.LobbyID != 0 || serverInfo.Endpoint != null)) ||
(selectedTab == ServerListTab.Recent && serverInfo.Recent) ||
(selectedTab == ServerListTab.Favorites && serverInfo.Favorite));
}
@@ -1105,7 +1086,7 @@ namespace Barotrauma
serverList.UpdateScrollBarSize();
}
private Queue<ServerInfo> pendingQueries = new Queue<ServerInfo>();
private readonly Queue<ServerInfo> pendingQueries = new Queue<ServerInfo>();
int activeQueries = 0;
private void QueueInfoQuery(ServerInfo info)
{
@@ -1152,46 +1133,22 @@ namespace Barotrauma
okButton.Enabled = false;
okButton.OnClicked = (btn, userdata) =>
{
JoinServer(endpointBox.Text, "");
if (!(Endpoint.Parse(endpointBox.Text).TryUnwrap(out var endpoint))) { return false; }
JoinServer(endpoint, "");
msgBox.Close();
return true;
return false;
};
var favoriteButton = msgBox.Buttons[1];
favoriteButton.Enabled = false;
favoriteButton.OnClicked = (button, userdata) =>
{
UInt64 steamId = SteamManager.SteamIDStringToUInt64(endpointBox.Text);
string ip = ""; int port = 0;
if (steamId == 0)
{
string hostIP = endpointBox.Text;
if (!(Endpoint.Parse(endpointBox.Text).TryUnwrap(out var endpoint))) { return false; }
string[] address = hostIP.Split(':');
if (address.Length == 1)
{
ip = hostIP;
port = NetConfig.DefaultPort;
}
else
{
ip = string.Join(":", address.Take(address.Length - 1));
if (!int.TryParse(address[address.Length - 1], out port))
{
DebugConsole.ThrowError("Invalid port: " + address[address.Length - 1] + "!");
port = NetConfig.DefaultPort;
}
}
}
//TODO: add a better way to get the query port, right now we're just assuming that it'll always be the default
ServerInfo serverInfo = new ServerInfo()
{
ServerName = "Server",
OwnerID = steamId,
IP = ip,
Port = port.ToString(),
QueryPort = NetConfig.DefaultQueryPort.ToString(),
Endpoint = endpoint,
GameVersion = GameMain.Version.ToString(),
PlayStyle = null
};
@@ -1231,37 +1188,25 @@ namespace Barotrauma
private bool JoinFriend(GUIButton button, object userdata)
{
FriendInfo info = userdata as FriendInfo;
if (!(userdata is FriendInfo { InServer: true } info)) { return false; }
if (info.InServer)
{
if (info.ConnectLobby != 0)
{
GameMain.Instance.ConnectLobby = info.ConnectLobby;
GameMain.Instance.ConnectEndpoint = null;
GameMain.Instance.ConnectName = null;
}
else
{
GameMain.Instance.ConnectLobby = 0;
GameMain.Instance.ConnectEndpoint = info.ConnectEndpoint;
GameMain.Instance.ConnectName = info.ConnectName;
}
}
GameMain.Instance.ConnectCommand = info.ConnectCommand;
return false;
}
private bool OpenFriendPopup(GUIButton button, object userdata)
{
FriendInfo info = userdata as FriendInfo;
if (!(userdata is FriendInfo { InServer: true } info)) { return false; }
if (info.InServer)
if (info.InServer
&& info.ConnectCommand is Some<ConnectCommand> { Value: { EndpointOrLobby: var endpointOrLobby } }
&& endpointOrLobby.TryGet(out ConnectCommand.NameAndEndpoint nameAndEndpoint))
{
int framePadding = 5;
const int framePadding = 5;
friendPopup = new GUIFrame(new RectTransform(Vector2.One, GUI.Canvas));
var serverNameText = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), friendPopup.RectTransform, Anchor.CenterLeft), info.ConnectName ?? "[Unnamed]");
var serverNameText = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), friendPopup.RectTransform, Anchor.CenterLeft), nameAndEndpoint.ServerName ?? "[Unnamed]");
serverNameText.RectTransform.AbsoluteOffset = new Point(framePadding, 0);
var joinButton = new GUIButton(new RectTransform(new Vector2(0.3f, 1.0f), friendPopup.RectTransform, Anchor.CenterRight), TextManager.Get("ServerListJoin"))
@@ -1349,7 +1294,7 @@ namespace Barotrauma
for (int i = friendsList.Count - 1; i >= 0; i--)
{
var friend = friendsList[i];
if (!friends.Any(g => g.Id == friend.SteamID && g.IsOnline))
if (!friends.Any(g => g.Id == friend.SteamId && g.IsOnline))
{
friend.Sprite?.Remove();
friendsList.RemoveAt(i);
@@ -1360,12 +1305,12 @@ namespace Barotrauma
{
if (!friend.IsOnline) { continue; }
FriendInfo info = friendsList.Find(f => f.SteamID == friend.Id);
FriendInfo info = friendsList.Find(f => f.SteamId == friend.Id);
if (info == null)
{
info = new FriendInfo()
{
SteamID = friend.Id
SteamId = friend.Id
};
friendsList.Insert(0, info);
}
@@ -1425,9 +1370,7 @@ namespace Barotrauma
info.Name = friend.Name;
info.ConnectName = null;
info.ConnectEndpoint = null;
info.ConnectLobby = 0;
info.ConnectCommand = Option<ConnectCommand>.None();
info.PlayingThisGame = friend.IsPlayingThisGame;
info.PlayingAnotherGame = friend.GameInfo.HasValue;
@@ -1439,7 +1382,7 @@ namespace Barotrauma
try
{
ToolBox.ParseConnectCommand(ToolBox.SplitCommand(connectCommand), out info.ConnectName, out info.ConnectEndpoint, out info.ConnectLobby);
info.ConnectCommand = ToolBox.ParseConnectCommand(ToolBox.SplitCommand(connectCommand));
}
catch (IndexOutOfRangeException e)
{
@@ -1448,9 +1391,7 @@ namespace Barotrauma
#else
DebugConsole.Log($"Failed to parse a Steam friend's connect command ({connectCommand})\n" + e.StackTrace.CleanupStackTrace());
#endif
info.ConnectName = null;
info.ConnectEndpoint = null;
info.ConnectLobby = 0;
info.ConnectCommand = Option<ConnectCommand>.None();
}
}
else
@@ -1650,86 +1591,16 @@ namespace Barotrauma
yield return CoroutineStatus.Success;
}
private void UpdateServerList(string masterServerData)
{
serverList.ClearChildren();
if (masterServerData.Substring(0, 5).Equals("error", StringComparison.OrdinalIgnoreCase))
{
DebugConsole.ThrowError("Error while connecting to master server (" + masterServerData + ")!");
return;
}
string[] lines = masterServerData.Split('\n');
List<ServerInfo> serverInfos = new List<ServerInfo>();
for (int i = 0; i < lines.Length; i++)
{
string[] arguments = lines[i].Split('|');
if (arguments.Length < 3) continue;
string ip = arguments[0];
string port = arguments[1];
string serverName = arguments[2];
bool gameStarted = arguments.Length > 3 && arguments[3] == "1";
string currPlayersStr = arguments.Length > 4 ? arguments[4] : "";
string maxPlayersStr = arguments.Length > 5 ? arguments[5] : "";
bool hasPassWord = arguments.Length > 6 && arguments[6] == "1";
string gameVersion = arguments.Length > 7 ? arguments[7] : "";
string contentPackageNames = arguments.Length > 8 ? arguments[8] : "";
string contentPackageHashes = arguments.Length > 9 ? arguments[9] : "";
int.TryParse(currPlayersStr, out int playerCount);
int.TryParse(maxPlayersStr, out int maxPlayers);
var serverInfo = new ServerInfo()
{
IP = ip,
Port = port,
ServerName = serverName,
GameStarted = gameStarted,
PlayerCount = playerCount,
MaxPlayers = maxPlayers,
HasPassword = hasPassWord,
GameVersion = gameVersion,
OwnerVerified = true
};
foreach (string contentPackageName in contentPackageNames.Split(','))
{
if (string.IsNullOrEmpty(contentPackageName)) continue;
serverInfo.ContentPackageNames.Add(contentPackageName);
}
foreach (string contentPackageHash in contentPackageHashes.Split(','))
{
if (string.IsNullOrEmpty(contentPackageHash)) continue;
serverInfo.ContentPackageHashes.Add(contentPackageHash);
}
serverInfos.Add(serverInfo);
}
serverList.Content.ClearChildren();
if (serverInfos.Count() == 0)
{
new GUITextBlock(new RectTransform(new Vector2(1.0f, 1.0f), serverList.Content.RectTransform),
TextManager.Get("NoServers"), textAlignment: Alignment.Center)
{
CanBeFocused = false
};
return;
}
foreach (ServerInfo serverInfo in serverInfos)
{
AddToServerList(serverInfo);
}
}
private GUIComponent FindFrameMatchingServerInfo(ServerInfo serverInfo)
=> serverList.Content.FindChild(d =>
d.UserData is ServerInfo info
&& (info.LobbyID == 0 || info.LobbyID == serverInfo.LobbyID)
&& info.OwnerVerified
&& serverInfo.Endpoint == info.Endpoint);
private void AddToServerList(ServerInfo serverInfo)
{
var serverFrame = serverList.Content.FindChild(d => (d.UserData is ServerInfo info) &&
(info.LobbyID == serverInfo.LobbyID ||
(info.LobbyID == 0 && info.OwnerID == serverInfo.OwnerID &&
serverInfo.OwnerVerified)) &&
(serverInfo.OwnerID != 0 ? true : (info.IP == serverInfo.IP && info.Port == serverInfo.Port)));
var serverFrame = FindFrameMatchingServerInfo(serverInfo);
if (serverFrame == null)
{
@@ -1763,8 +1634,10 @@ namespace Barotrauma
if (serverInfo.OwnerVerified)
{
var childrenToRemove = serverList.Content.FindChildren(c => (c.UserData is ServerInfo info) && info != serverInfo &&
(serverInfo.OwnerID != 0 ? info.OwnerID == serverInfo.OwnerID : info.IP == serverInfo.IP)).ToList();
var childrenToRemove = serverList.Content.FindChildren(c =>
c.UserData is ServerInfo info
&& !ReferenceEquals(info, serverInfo)
&& serverInfo.Endpoint == info.Endpoint).ToList();
foreach (var child in childrenToRemove)
{
serverList.Content.RemoveChild(child);
@@ -1779,11 +1652,7 @@ namespace Barotrauma
private void UpdateServerInfo(ServerInfo serverInfo)
{
var serverFrame = serverList.Content.FindChild(d => (d.UserData is ServerInfo info) &&
(info.LobbyID == serverInfo.LobbyID ||
(info.LobbyID == 0 && info.OwnerID == serverInfo.OwnerID &&
serverInfo.OwnerVerified)) &&
(serverInfo.OwnerID != 0 ? true : (info.IP == serverInfo.IP && info.Port == serverInfo.Port)));
var serverFrame = FindFrameMatchingServerInfo(serverInfo);
if (serverFrame == null) return;
var serverContent = serverFrame.Children.First() as GUILayoutGroup;
@@ -1806,11 +1675,10 @@ namespace Barotrauma
};
var serverName = new GUITextBlock(new RectTransform(new Vector2(columnRelativeWidth[2] * 1.1f, 1.0f), serverContent.RectTransform),
#if !DEBUG
serverInfo.ServerName,
#else
((serverInfo.OwnerID != 0 || serverInfo.LobbyID != 0) ? "[STEAMP2P] " : "[LIDGREN] ") + serverInfo.ServerName,
#if DEBUG
(serverInfo.Endpoint is SteamP2PEndpoint ? "[STEAMP2P] " : "[LIDGREN] ") +
#endif
serverInfo.ServerName,
style: "GUIServerListTextBox");
serverName.UserData = serverName.Text;
serverName.RectTransform.SizeChanged += () =>
@@ -1850,7 +1718,7 @@ namespace Barotrauma
serverPingText.Text = serverInfo.Ping > -1 ? serverInfo.Ping.ToString() : "?";
serverPingText.TextColor = GetPingTextColor(serverInfo.Ping);
}
else if (!string.IsNullOrEmpty(serverInfo.IP))
else if (serverInfo.Endpoint is LidgrenEndpoint lidgrenEndpoint)
{
try
{
@@ -1866,7 +1734,7 @@ namespace Barotrauma
CoroutineManager.StartCoroutine(EstimateLobbyPing(serverInfo, serverPingText), "EstimateLobbyPing");
}
if (serverInfo.LobbyID == 0 && (string.IsNullOrWhiteSpace(serverInfo.IP) || string.IsNullOrWhiteSpace(serverInfo.Port)))
if (serverInfo.LobbyID == 0)
{
LocalizedString toolTip = TextManager.Get("ServerOffline");
serverContent.Children.ForEach(c => c.ToolTip = toolTip);
@@ -1930,7 +1798,7 @@ namespace Barotrauma
LocalizedString toolTip = "";
for (int i = 0; i < serverInfo.ContentPackageNames.Count; i++)
{
if (!ContentPackageManager.EnabledPackages.All.Any(contentPackage => contentPackage.Hash.StringRepresentation == serverInfo.ContentPackageHashes[i]))
if (ContentPackageManager.EnabledPackages.All.None(contentPackage => contentPackage.Hash.StringRepresentation == serverInfo.ContentPackageHashes[i]))
{
if (toolTip != "") { toolTip += "\n"; }
toolTip += TextManager.GetWithVariable("ServerListIncompatibleContentPackageWorkshopAvailable", "[contentpackage]", serverInfo.ContentPackageNames[i]);
@@ -1995,7 +1863,7 @@ namespace Barotrauma
masterServerResponded = true;
}
private bool JoinServer(string endpoint, string serverName)
private bool JoinServer(Endpoint endpoint, string serverName)
{
if (string.IsNullOrWhiteSpace(ClientNameBox.Text))
{
@@ -2013,17 +1881,13 @@ namespace Barotrauma
return true;
}
private IEnumerable<CoroutineStatus> ConnectToServer(string endpoint, string serverName)
private IEnumerable<CoroutineStatus> ConnectToServer(Endpoint endpoint, string serverName)
{
string serverIP = null;
UInt64 serverSteamID = SteamManager.SteamIDStringToUInt64(endpoint);
if (serverSteamID == 0) { serverIP = endpoint; }
#if !DEBUG
try
{
#endif
GameMain.Client = new GameClient(MultiplayerPreferences.Instance.PlayerName.FallbackNullOrEmpty(SteamManager.GetUsername()), serverIP, serverSteamID, serverName);
GameMain.Client = new GameClient(MultiplayerPreferences.Instance.PlayerName.FallbackNullOrEmpty(SteamManager.GetUsername()), endpoint, serverName, Option<int>.None());
#if !DEBUG
}
catch (Exception e)
@@ -2035,31 +1899,32 @@ namespace Barotrauma
yield return CoroutineStatus.Success;
}
public void GetServerPing(ServerInfo serverInfo, GUITextBlock serverPingText)
private void GetServerPing(ServerInfo serverInfo, GUITextBlock serverPingText)
{
if (CoroutineManager.IsCoroutineRunning("ConnectToServer")) { return; }
if (!(serverInfo.Endpoint is LidgrenEndpoint { NetEndpoint: { Address: var address } })) { return; }
lock (activePings)
{
if (activePings.ContainsKey(serverInfo.IP)) { return; }
activePings.Add(serverInfo.IP, activePings.Any() ? activePings.Values.Max()+1 : 0);
if (activePings.ContainsKey(address)) { return; }
activePings.Add(address, activePings.Any() ? activePings.Values.Max()+1 : 0);
}
serverInfo.PingChecked = false;
serverInfo.Ping = -1;
TaskPool.Add($"PingServerAsync ({serverInfo?.IP ?? "NULL"})", PingServerAsync(serverInfo.IP, 1000),
TaskPool.Add($"PingServerAsync ({address})", PingServerAsync(address, 1000),
new Tuple<ServerInfo, GUITextBlock>(serverInfo, serverPingText),
(rtt, obj) =>
{
var info = obj.Item1;
var text = obj.Item2;
rtt.TryGetResult(out info.Ping); info.PingChecked = true;
var (info, text) = obj;
if (!rtt.TryGetResult(out info.Ping)) { info.Ping = -1; }
info.PingChecked = true;
text.TextColor = GetPingTextColor(info.Ping);
text.Text = info.Ping > -1 ? info.Ping.ToString() : "?";
lock (activePings)
{
activePings.Remove(info.IP);
activePings.Remove(address);
}
});
}
@@ -2070,7 +1935,7 @@ namespace Barotrauma
return ToolBox.GradientLerp(ping / 200.0f, GUIStyle.Green, GUIStyle.Orange, GUIStyle.Red);
}
public async Task<int> PingServerAsync(string ip, int timeOut)
public async Task<int> PingServerAsync(IPAddress ipAddress, int timeOut)
{
await Task.Yield();
bool shouldGo = false;
@@ -2078,29 +1943,22 @@ namespace Barotrauma
{
lock (activePings)
{
shouldGo = activePings.Count(kvp => kvp.Value < activePings[ip]) < 25;
shouldGo = activePings.Count(kvp => kvp.Value < activePings[ipAddress]) < 25;
}
await Task.Delay(25);
}
if (string.IsNullOrWhiteSpace(ip))
{
return -1;
}
long rtt = -1;
IPAddress address = null;
IPAddress.TryParse(ip, out address);
if (address != null)
if (ipAddress != null)
{
//don't attempt to ping if the address is IPv6 and it's not supported
if (address.AddressFamily != AddressFamily.InterNetworkV6 || Socket.OSSupportsIPv6)
if (ipAddress.AddressFamily != AddressFamily.InterNetworkV6 || Socket.OSSupportsIPv6)
{
Ping ping = new Ping();
byte[] buffer = new byte[32];
try
{
PingReply pingReply = ping.Send(address, timeOut, buffer, new PingOptions(128, true));
PingReply pingReply = ping.Send(ipAddress, timeOut, buffer, new PingOptions(128, true));
if (pingReply != null)
{
@@ -2117,9 +1975,9 @@ namespace Barotrauma
}
catch (Exception ex)
{
GameAnalyticsManager.AddErrorEventOnce("ServerListScreen.PingServer:PingException" + ip, GameAnalyticsManager.ErrorSeverity.Warning, "Failed to ping a server - " + (ex?.InnerException?.Message ?? ex.Message));
GameAnalyticsManager.AddErrorEventOnce("ServerListScreen.PingServer:PingException" + ipAddress, GameAnalyticsManager.ErrorSeverity.Warning, "Failed to ping a server - " + (ex?.InnerException?.Message ?? ex.Message));
#if DEBUG
DebugConsole.NewMessage("Failed to ping a server (" + ip + ") - " + (ex?.InnerException?.Message ?? ex.Message), Color.Red);
DebugConsole.NewMessage("Failed to ping a server (" + ipAddress + ") - " + (ex?.InnerException?.Message ?? ex.Message), Color.Red);
#endif
}
}
@@ -149,7 +149,7 @@ namespace Barotrauma
private GUIDropDown linkedSubBox;
private static GUIComponent autoSaveLabel;
private static int maxAutoSaves => GameSettings.CurrentConfig.MaxAutoSaves;
private static int MaxAutoSaves => GameSettings.CurrentConfig.MaxAutoSaves;
public static readonly object ItemAddMutex = new object(), ItemRemoveMutex = new object();
@@ -228,6 +228,8 @@ namespace Barotrauma
private static bool isAutoSaving;
private KeyOrMouse toggleEntityListBind;
public override Camera Cam => cam;
public static XDocument AutoSaveInfo;
@@ -926,7 +928,6 @@ namespace Barotrauma
toggleEntityMenuButton = new GUIButton(new RectTransform(new Vector2(0.15f, 0.08f), EntityMenu.RectTransform, Anchor.TopCenter, Pivot.BottomCenter) { MinSize = new Point(0, 15) },
style: "UIToggleButtonVertical")
{
ToolTip = RichString.Rich($"{TextManager.Get("EntityMenuToggleTooltip")}\n‖color:125,125,125‖{GameSettings.CurrentConfig.KeyMap.Bindings[InputType.ToggleInventory].Name}‖color:end‖"),
OnClicked = (btn, userdata) =>
{
entityMenuOpen = !entityMenuOpen;
@@ -1645,7 +1646,7 @@ namespace Barotrauma
if (AutoSaveInfo?.Root == null || MainSub?.Info == null) { return; }
int saveCount = AutoSaveInfo.Root.Elements().Count();
while (AutoSaveInfo.Root.Elements().Count() > maxAutoSaves)
while (AutoSaveInfo.Root.Elements().Count() > MaxAutoSaves)
{
XElement min = AutoSaveInfo.Root.Elements().OrderBy(element => element.GetAttributeUInt64("time", 0)).FirstOrDefault();
#warning TODO: revise
@@ -5192,6 +5193,11 @@ namespace Barotrauma
}
}
if (toggleEntityListBind != GameSettings.CurrentConfig.KeyMap.Bindings[InputType.ToggleInventory])
{
toggleEntityMenuButton.ToolTip = RichString.Rich($"{TextManager.Get("EntityMenuToggleTooltip")}\n‖color:125,125,125‖{GameSettings.CurrentConfig.KeyMap.Bindings[InputType.ToggleInventory].Name}‖color:end‖");
toggleEntityListBind = GameSettings.CurrentConfig.KeyMap.Bindings[InputType.ToggleInventory];
}
if (GameSettings.CurrentConfig.KeyMap.Bindings[InputType.ToggleInventory].IsHit() && mode == Mode.Default)
{
toggleEntityMenuButton.OnClicked?.Invoke(toggleEntityMenuButton, toggleEntityMenuButton.UserData);
@@ -5528,8 +5534,10 @@ namespace Barotrauma
MouseDragStart = Vector2.Zero;
}
if (!saveAssemblyFrame.Rect.Contains(PlayerInput.MousePosition) && !snapToGridFrame.Rect.Contains(PlayerInput.MousePosition) &&
dummyCharacter?.SelectedItem == null && !WiringMode && GUI.MouseOn == null)
if (!saveAssemblyFrame.Rect.Contains(PlayerInput.MousePosition)
&& !snapToGridFrame.Rect.Contains(PlayerInput.MousePosition)
&& dummyCharacter?.SelectedItem == null && !WiringMode
&& (GUI.MouseOn == null || MapEntity.SelectedAny || MapEntity.SelectionPos != Vector2.Zero))
{
if (layerList is { Visible: true } && GUI.KeyboardDispatcher.Subscriber == layerList)
{
@@ -5556,7 +5564,7 @@ namespace Barotrauma
{
bool shouldCloseHud = dummyCharacter?.SelectedItem != null && HUD.CloseHUD(dummyCharacter.SelectedItem.Rect) && DraggedItemPrefab == null;
if (MapEntityPrefab.Selected != null && GUI.MouseOn == null)
if (MapEntityPrefab.Selected != null)
{
MapEntityPrefab.Selected.UpdatePlacing(cam);
}
@@ -5708,7 +5716,7 @@ namespace Barotrauma
spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.NonPremultiplied, transformMatrix: cam.Transform);
Submarine.DrawFront(spriteBatch, editing: true, e => !IsSubcategoryHidden(e.Prefab?.Subcategory));
if (!WiringMode && !IsMouseOnEditorGUI())
if (!WiringMode)
{
MapEntityPrefab.Selected?.DrawPlacing(spriteBatch, cam);
MapEntity.DrawSelecting(spriteBatch, cam);