(965c31410a) Unstable v0.10.4.0

This commit is contained in:
Juan Pablo Arce
2020-07-21 08:57:50 -03:00
parent 4f8bd39789
commit 33d3a41104
546 changed files with 45952 additions and 25762 deletions
@@ -19,6 +19,7 @@ namespace Barotrauma.Networking
ChatMessageType type = (ChatMessageType)msg.ReadByte();
PlayerConnectionChangeType changeType = PlayerConnectionChangeType.None;
string txt = "";
string styleSetting = string.Empty;
if (type != ChatMessageType.Order)
{
@@ -38,59 +39,65 @@ namespace Barotrauma.Networking
}
}
if (type == ChatMessageType.ServerMessageBox)
switch (type)
{
txt = TextManager.GetServerMessage(txt);
}
else if (type == ChatMessageType.Order)
{
int orderIndex = msg.ReadByte();
UInt16 targetCharacterID = msg.ReadUInt16();
Character targetCharacter = Entity.FindEntityByID(targetCharacterID) as Character;
Entity targetEntity = Entity.FindEntityByID(msg.ReadUInt16());
int optionIndex = msg.ReadByte();
case ChatMessageType.Default:
break;
case ChatMessageType.Order:
int orderIndex = msg.ReadByte();
UInt16 targetCharacterID = msg.ReadUInt16();
Character targetCharacter = Entity.FindEntityByID(targetCharacterID) as Character;
Entity targetEntity = Entity.FindEntityByID(msg.ReadUInt16());
int optionIndex = msg.ReadByte();
Order order = null;
if (orderIndex < 0 || orderIndex >= Order.PrefabList.Count)
{
DebugConsole.ThrowError("Invalid order message - order index out of bounds.");
if (NetIdUtils.IdMoreRecent(ID, LastID)) LastID = ID;
Order order = null;
if (orderIndex < 0 || orderIndex >= Order.PrefabList.Count)
{
DebugConsole.ThrowError("Invalid order message - order index out of bounds.");
if (NetIdUtils.IdMoreRecent(ID, LastID)) LastID = ID;
return;
}
else
{
order = Order.PrefabList[orderIndex];
}
string orderOption = "";
if (optionIndex >= 0 && optionIndex < order.Options.Length)
{
orderOption = order.Options[optionIndex];
}
txt = order.GetChatMessage(targetCharacter?.Name, senderCharacter?.CurrentHull?.DisplayName, givingOrderToSelf: targetCharacter == senderCharacter, orderOption: orderOption);
if (GameMain.Client.GameStarted && Screen.Selected == GameMain.GameScreen)
{
if (order.TargetAllCharacters)
{
GameMain.GameSession?.CrewManager?.AddOrder(
new Order(order.Prefab, targetEntity, (targetEntity as Item)?.Components.FirstOrDefault(ic => ic.GetType() == order.ItemComponentType), orderGiver: senderCharacter),
order.Prefab.FadeOutTime);
}
else if (targetCharacter != null)
{
targetCharacter.SetOrder(
new Order(order.Prefab, targetEntity, (targetEntity as Item)?.Components.FirstOrDefault(ic => ic.GetType() == order.ItemComponentType), orderGiver: senderCharacter),
orderOption, senderCharacter);
}
}
if (NetIdUtils.IdMoreRecent(ID, LastID))
{
GameMain.Client.AddChatMessage(
new OrderChatMessage(order, orderOption, txt, targetEntity, targetCharacter, senderCharacter));
LastID = ID;
}
return;
}
else
{
order = Order.PrefabList[orderIndex];
}
string orderOption = "";
if (optionIndex >= 0 && optionIndex < order.Options.Length)
{
orderOption = order.Options[optionIndex];
}
txt = order.GetChatMessage(targetCharacter?.Name, senderCharacter?.CurrentHull?.DisplayName, givingOrderToSelf: targetCharacter == senderCharacter, orderOption: orderOption);
if (GameMain.Client.GameStarted && Screen.Selected == GameMain.GameScreen)
{
if (order.TargetAllCharacters)
{
GameMain.GameSession?.CrewManager?.AddOrder(
new Order(order.Prefab, targetEntity, (targetEntity as Item)?.Components.FirstOrDefault(ic => ic.GetType() == order.ItemComponentType), orderGiver: senderCharacter),
order.Prefab.FadeOutTime);
}
else if (targetCharacter != null)
{
targetCharacter.SetOrder(
new Order(order.Prefab, targetEntity, (targetEntity as Item)?.Components.FirstOrDefault(ic => ic.GetType() == order.ItemComponentType), orderGiver: senderCharacter),
orderOption, senderCharacter);
}
}
if (NetIdUtils.IdMoreRecent(ID, LastID))
{
GameMain.Client.AddChatMessage(
new OrderChatMessage(order, orderOption, txt, targetEntity, targetCharacter, senderCharacter));
LastID = ID;
}
return;
case ChatMessageType.ServerMessageBox:
txt = TextManager.GetServerMessage(txt);
break;
case ChatMessageType.ServerMessageBoxInGame:
styleSetting = msg.ReadString();
txt = TextManager.GetServerMessage(txt);
break;
}
if (NetIdUtils.IdMoreRecent(ID, LastID))
@@ -105,6 +112,9 @@ namespace Barotrauma.Networking
new GUIMessageBox("", txt);
}
break;
case ChatMessageType.ServerMessageBoxInGame:
new GUIMessageBox("", txt, new string[0], type: GUIMessageBox.Type.InGame, iconStyle: styleSetting);
break;
case ChatMessageType.Console:
DebugConsole.NewMessage(txt, MessageColor[(int)ChatMessageType.Console]);
break;
@@ -120,7 +130,7 @@ namespace Barotrauma.Networking
break;
}
LastID = ID;
}
}
}
}
}
@@ -18,6 +18,7 @@ namespace Barotrauma.Networking
public bool Muted;
public bool InGame;
public bool HasPermissions;
public bool IsOwner;
public bool AllowKicking;
}
@@ -44,6 +45,8 @@ namespace Barotrauma.Networking
}
}
public bool IsOwner;
public bool AllowKicking;
public float Karma;
@@ -121,7 +121,7 @@ namespace Barotrauma.Networking
if (GameSettings.VerboseLogging)
{
DebugConsole.Log("Received " + all.Length + " bytes of the file " + FileName + " (" + Received + "/" + FileSize + " received)");
DebugConsole.Log($"Received {all.Length} bytes of the file {FileName} ({Received / 1000}/{FileSize / 1000} kB received)");
}
BytesPerSecond = Received / psec;
@@ -332,17 +332,14 @@ namespace Barotrauma.Networking
}
int offset = inc.ReadInt32();
int bytesToRead = inc.ReadUInt16();
if (offset != activeTransfer.Received)
{
if (offset < activeTransfer.Received)
{
GameMain.Client.UpdateFileTransfer(activeTransfer.ID, activeTransfer.Received);
}
DebugConsole.Log($"Received {bytesToRead} bytes of the file {activeTransfer.FileName} (ignoring: offset {offset}, waiting for {activeTransfer.Received})");
GameMain.Client.UpdateFileTransfer(activeTransfer.ID, activeTransfer.Received);
return;
}
int bytesToRead = inc.ReadUInt16();
if (activeTransfer.Received + bytesToRead > activeTransfer.FileSize)
{
GameMain.Client.CancelFileTransfer(transferId);
@@ -358,7 +355,7 @@ namespace Barotrauma.Networking
try
{
activeTransfer.ReadBytes(inc, bytesToRead);
activeTransfer.ReadBytes(inc, bytesToRead);
}
catch (Exception e)
{
@@ -369,9 +366,9 @@ namespace Barotrauma.Networking
return;
}
GameMain.Client.UpdateFileTransfer(activeTransfer.ID, activeTransfer.Received, reliable: activeTransfer.Status == FileTransferStatus.Finished);
if (activeTransfer.Status == FileTransferStatus.Finished)
{
GameMain.Client.UpdateFileTransfer(activeTransfer.ID, activeTransfer.Received, true);
activeTransfer.Dispose();
if (ValidateReceivedData(activeTransfer, out string errorMessage))
File diff suppressed because it is too large Load Diff
@@ -4,6 +4,7 @@ using System.Text;
using System.Linq;
using Barotrauma.Steam;
using System.Threading;
using Barotrauma.Items.Components;
namespace Barotrauma.Networking
{
@@ -17,6 +18,7 @@ namespace Barotrauma.Networking
private Steamworks.AuthTicket steamAuthTicket;
private double timeout;
private double heartbeatTimer;
private double connectionStatusTimer;
private long sentBytes, receivedBytes;
@@ -53,6 +55,9 @@ namespace Barotrauma.Networking
Steamworks.SteamNetworking.ResetActions();
Steamworks.SteamNetworking.OnP2PSessionRequest = OnIncomingConnection;
Steamworks.SteamNetworking.OnP2PConnectionFailed = OnConnectionFailed;
Steamworks.SteamNetworking.AllowP2PPacketRelay(true);
ServerConnection = new SteamP2PConnection("Server", hostSteamId);
@@ -71,6 +76,7 @@ namespace Barotrauma.Networking
timeout = NetworkConnection.TimeoutThreshold;
heartbeatTimer = 1.0;
connectionStatusTimer = 0.0;
isActive = true;
}
@@ -78,7 +84,25 @@ namespace Barotrauma.Networking
private void OnIncomingConnection(Steamworks.SteamId steamId)
{
if (!isActive) { return; }
if (steamId == hostSteamId) { Steamworks.SteamNetworking.AcceptP2PSessionWithUser(steamId); }
if (steamId == hostSteamId)
{
Steamworks.SteamNetworking.AcceptP2PSessionWithUser(steamId);
}
else if (initializationStep != ConnectionInitialization.Password &&
initializationStep != ConnectionInitialization.Success)
{
DebugConsole.ThrowError($"Connection from incorrect SteamID was rejected: "+
$"expected {SteamManager.SteamIDUInt64ToString(hostSteamId)}," +
$"got {SteamManager.SteamIDUInt64ToString(steamId)}");
}
}
private void OnConnectionFailed(Steamworks.SteamId steamId, Steamworks.P2PSessionError error)
{
if (!isActive) { return; }
if (steamId != hostSteamId) { return; }
Close($"SteamP2P connection failed: {error}");
OnDisconnectMessageReceived?.Invoke($"SteamP2P connection failed: {error}");
}
private void OnP2PData(ulong steamId, byte[] data, int dataLength, int channel)
@@ -140,6 +164,30 @@ namespace Barotrauma.Networking
timeout -= deltaTime;
heartbeatTimer -= deltaTime;
if (initializationStep != ConnectionInitialization.Password &&
initializationStep != ConnectionInitialization.Success)
{
connectionStatusTimer -= deltaTime;
if (connectionStatusTimer <= 0.0)
{
var state = Steamworks.SteamNetworking.GetP2PSessionState(hostSteamId);
if (state == null)
{
Close("SteamP2P connection could not be established");
OnDisconnectMessageReceived?.Invoke("SteamP2P connection could not be established");
}
else
{
if (state?.P2PSessionError != Steamworks.P2PSessionError.None)
{
Close($"SteamP2P error code: {state?.P2PSessionError}");
OnDisconnectMessageReceived?.Invoke($"SteamP2P error code: {state?.P2PSessionError}");
}
}
connectionStatusTimer = 1.0f;
}
}
for (int i = 0; i < 100; i++)
{
if (!Steamworks.SteamNetworking.IsP2PPacketAvailable()) { break; }
@@ -70,6 +70,8 @@ namespace Barotrauma.Networking
Steamworks.SteamNetworking.OnP2PSessionRequest = OnIncomingConnection;
Steamworks.SteamUser.OnValidateAuthTicketResponse += OnAuthChange;
Steamworks.SteamNetworking.AllowP2PPacketRelay(true);
isActive = true;
}
@@ -15,7 +15,7 @@ namespace Barotrauma.Networking
public string Port;
public string QueryPort;
public Steamworks.Data.PingLocation? PingLocation;
public Steamworks.Data.NetPingLocation? PingLocation;
public UInt64 LobbyID;
public UInt64 OwnerID;
public bool OwnerVerified;
@@ -60,7 +60,7 @@ namespace Barotrauma.Networking
public bool? RespondedToSteamQuery = null;
public Steamworks.Friend? SteamFriend;
public Steamworks.ISteamMatchmakingPingResponse MatchmakingPingResponse;
public Steamworks.SteamMatchmakingPingResponse MatchmakingPingResponse;
public string GameVersion;
public List<string> ContentPackageNames
@@ -401,7 +401,7 @@ namespace Barotrauma.Networking
return info;
}
public void QueryLiveInfo(Action<Networking.ServerInfo> onServerRulesReceived)
public void QueryLiveInfo(Action<Networking.ServerInfo> onServerRulesReceived, Action<Networking.ServerInfo> onQueryDone)
{
if (!SteamManager.IsInitialized) { return; }
@@ -412,7 +412,7 @@ namespace Barotrauma.Networking
MatchmakingPingResponse.Cancel();
}
MatchmakingPingResponse = new Steamworks.ISteamMatchmakingPingResponse(
MatchmakingPingResponse = new Steamworks.SteamMatchmakingPingResponse(
(server) =>
{
ServerName = server.Name;
@@ -423,22 +423,20 @@ namespace Barotrauma.Networking
PingChecked = true;
Ping = server.Ping;
LobbyID = 0;
TaskPool.Add(server.QueryRulesAsync(),
TaskPool.Add("QueryServerRules (QueryLiveInfo)", server.QueryRulesAsync(),
(t) =>
{
onQueryDone(this);
if (t.Status == TaskStatus.Faulted)
{
TaskPool.PrintTaskExceptions(t, "Failed to retrieve rules for " + ServerName);
return;
}
var rules = t.Result;
var rules = ((Task<Dictionary<string, string>>)t).Result;
SteamManager.AssignServerRulesToServerInfo(rules, this);
CrossThread.RequestExecutionOnMainThread(() =>
{
onServerRulesReceived(this);
});
onServerRulesReceived(this);
});
},
() =>
@@ -456,9 +454,10 @@ namespace Barotrauma.Networking
}
if (LobbyID == 0)
{
TaskPool.Add(SteamFriend?.RequestInfoAsync(),
TaskPool.Add("RequestSteamP2POwnerInfo", SteamFriend?.RequestInfoAsync(),
(t) =>
{
onQueryDone(this);
if ((SteamFriend?.IsPlayingThisGame ?? false) && ((SteamFriend?.GameInfo?.Lobby?.Id ?? 0) != 0))
{
LobbyID = SteamFriend?.GameInfo?.Lobby?.Id.Value ?? 0;
@@ -471,6 +470,10 @@ namespace Barotrauma.Networking
}
});
}
else
{
onQueryDone(this);
}
}
}
@@ -766,6 +766,14 @@ namespace Barotrauma.Networking
TextManager.Get("ServerSettingsAllowFriendlyFire"));
GetPropertyData("AllowFriendlyFire").AssignGUIComponent(allowFriendlyFire);
var killableNPCs = new GUITickBox(new RectTransform(new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
TextManager.Get("ServerSettingsKillableNPCs"));
GetPropertyData("KillableNPCs").AssignGUIComponent(killableNPCs);
var destructibleOutposts = new GUITickBox(new RectTransform(new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
TextManager.Get("ServerSettingsDestructibleOutposts"));
GetPropertyData("DestructibleOutposts").AssignGUIComponent(destructibleOutposts);
var allowRewiring = new GUITickBox(new RectTransform(new Vector2(0.48f, 0.05f), tickBoxContainer.Content.RectTransform),
TextManager.Get("ServerSettingsAllowRewiring"));
GetPropertyData("AllowRewiring").AssignGUIComponent(allowRewiring);
@@ -10,6 +10,7 @@ using RestSharp.Contrib;
using System.Xml.Linq;
using Color = Microsoft.Xna.Framework.Color;
using System.Runtime.InteropServices;
using NLog.Fluent;
namespace Barotrauma.Steam
{
@@ -29,7 +30,7 @@ namespace Barotrauma.Steam
if (isInitialized)
{
DebugConsole.NewMessage("Logged in as " + GetUsername() + " (SteamID " + SteamIDUInt64ToString(GetSteamID()) + ")");
popularTags.Clear();
int i = 0;
foreach (KeyValuePair<string, int> commonness in tagCommonness)
@@ -37,19 +38,16 @@ namespace Barotrauma.Steam
popularTags.Insert(i, commonness.Key);
i++;
}
LogSteamworksNetworkingDelegate = LogSteamworksNetworking;
IntPtr logSteamworksNetworkingPtr = Marshal.GetFunctionPointerForDelegate(LogSteamworksNetworkingDelegate);
Steamworks.SteamNetworkingUtils.SetDebugOutputFunction(Steamworks.Data.DebugOutputType.Everything, logSteamworksNetworkingPtr);
}
Steamworks.SteamNetworkingUtils.OnDebugOutput += LogSteamworksNetworking;
}
catch (DllNotFoundException)
{
isInitialized = false;
initializationErrors.Add("SteamDllNotFound");
}
catch (Exception)
catch (Exception e)
{
isInitialized = false;
initializationErrors.Add("SteamClientInitFailed");
@@ -70,13 +68,24 @@ namespace Barotrauma.Steam
public static bool NetworkingDebugLog = false;
private static Steamworks.Data.FSteamNetworkingSocketsDebugOutput LogSteamworksNetworkingDelegate;
private static void LogSteamworksNetworking(Steamworks.Data.DebugOutputType nType, string pszMsg)
private static void LogSteamworksNetworking(Steamworks.NetDebugOutput nType, string pszMsg)
{
if (NetworkingDebugLog) { DebugConsole.NewMessage($"({nType}) {pszMsg}", Color.Orange); }
DebugConsole.NewMessage($"({nType}) {pszMsg}", Color.Orange);
}
public static void SetSteamworksNetworkingDebugLog(bool enabled)
{
if (enabled)
{
Steamworks.SteamNetworkingUtils.DebugLevel = Steamworks.NetDebugOutput.Everything;
}
else
{
Steamworks.SteamNetworkingUtils.DebugLevel = Steamworks.NetDebugOutput.None;
}
}
private static void UpdateProjectSpecific(float deltaTime)
{
if (ugcSubscriptionTasks != null)
@@ -98,6 +107,34 @@ namespace Barotrauma.Steam
}
}
public static async Task InitRelayNetworkAccess()
{
if (!IsInitialized) { return; }
await Task.Yield();
Steamworks.SteamNetworkingUtils.InitRelayNetworkAccess();
SetSteamworksNetworkingDebugLog(true);
var status = Steamworks.SteamNetworkingUtils.Status;
while (status.Avail != Steamworks.SteamNetworkingAvailability.Current)
{
if (status.Avail == Steamworks.SteamNetworkingAvailability.CannotTry ||
status.Avail == Steamworks.SteamNetworkingAvailability.Previously ||
status.Avail == Steamworks.SteamNetworkingAvailability.Failed)
{
DebugConsole.ThrowError($"Failed to initialize Steamworks network relay: " +
$"{Steamworks.SteamNetworkingUtils.Status.Avail}, " +
$"{Steamworks.SteamNetworkingUtils.Status.AvailNetConfig}, " +
$"{Steamworks.SteamNetworkingUtils.Status.Avail}, " +
$"{Steamworks.SteamNetworkingUtils.Status.Msg}");
break;
}
await Task.Delay(25);
status = Steamworks.SteamNetworkingUtils.Status;
}
SetSteamworksNetworkingDebugLog(false);
}
private enum LobbyState
{
NotConnected,
@@ -118,10 +155,16 @@ namespace Barotrauma.Steam
{
if (lobbyState != LobbyState.NotConnected) { return; }
lobbyState = LobbyState.Creating;
TaskPool.Add(Steamworks.SteamMatchmaking.CreateLobbyAsync(serverSettings.MaxPlayers + 10),
TaskPool.Add("CreateLobbyAsync", Steamworks.SteamMatchmaking.CreateLobbyAsync(serverSettings.MaxPlayers + 10),
(lobby) =>
{
currentLobby = lobby.Result;
if (lobbyState != LobbyState.Creating)
{
LeaveLobby();
return;
}
currentLobby = ((Task<Steamworks.Data.Lobby?>)lobby).Result;
if (currentLobby == null)
{
@@ -218,10 +261,10 @@ namespace Barotrauma.Steam
lobbyState = LobbyState.Joining;
lobbyID = id;
TaskPool.Add(Steamworks.SteamMatchmaking.JoinLobbyAsync(lobbyID),
TaskPool.Add("JoinLobbyAsync", Steamworks.SteamMatchmaking.JoinLobbyAsync(lobbyID),
(lobby) =>
{
currentLobby = lobby.Result;
currentLobby = ((Task<Steamworks.Data.Lobby?>)lobby).Result;
lobbyState = LobbyState.Joined;
lobbyID = (currentLobby?.Id).Value;
if (joinServer)
@@ -252,9 +295,10 @@ namespace Barotrauma.Steam
//TODO: find a better strategy to fetch all lobbies, this is gonna take forever if we actually have 10000 lobbies
Steamworks.Data.LobbyQuery lobbyQuery = Steamworks.SteamMatchmaking.CreateLobbyQuery().FilterDistanceWorldwide().WithMaxResults(10000);
TaskPool.Add(Task.Run(async () =>
TaskPool.Add("LobbyQueryRequest", lobbyQuery.RequestAsync(),
(t) =>
{
Steamworks.Data.Lobby[] lobbies = await lobbyQuery.RequestAsync();
var lobbies = ((Task<Steamworks.Data.Lobby[]>)t).Result;
foreach (var lobby in lobbies)
{
if (string.IsNullOrEmpty(lobby.GetData("name"))) { continue; }
@@ -270,14 +314,8 @@ namespace Barotrauma.Steam
AssignLobbyDataToServerInfo(lobby, serverInfo);
CrossThread.RequestExecutionOnMainThread(() =>
{
addToServerList(serverInfo);
});
addToServerList(serverInfo);
}
}),
(t) =>
{
taskDone();
if (t.Status == TaskStatus.Faulted)
{
@@ -301,7 +339,7 @@ namespace Barotrauma.Steam
if (responsive)
{
TaskPool.Add(info.QueryRulesAsync(),
TaskPool.Add($"QueryServerRules (GetServers, {info.Name}, {info.Address})", info.QueryRulesAsync(),
(t) =>
{
if (t.Status == TaskStatus.Faulted)
@@ -310,7 +348,7 @@ namespace Barotrauma.Steam
return;
}
var rules = t.Result;
var rules = ((Task<Dictionary<string,string>>)t).Result;
AssignServerRulesToServerInfo(rules, serverInfo);
CrossThread.RequestExecutionOnMainThread(() =>
@@ -331,7 +369,7 @@ namespace Barotrauma.Steam
serverQuery.OnResponsiveServer += (info) => onServer(info, true);
serverQuery.OnUnresponsiveServer += (info) => onServer(info, false);
TaskPool.Add(serverQuery.RunQueryAsync(),
TaskPool.Add("RunServerQuery", serverQuery.RunQueryAsync(),
(t) =>
{
serverQuery.Dispose();
@@ -384,7 +422,7 @@ namespace Barotrauma.Steam
string pingLocation = lobby.GetData("pinglocation");
if (!string.IsNullOrEmpty(pingLocation))
{
serverInfo.PingLocation = Steamworks.Data.PingLocation.TryParseFromString(pingLocation);
serverInfo.PingLocation = Steamworks.Data.NetPingLocation.TryParseFromString(pingLocation);
}
bool? getLobbyBool(string key)
@@ -570,7 +608,7 @@ namespace Barotrauma.Steam
.WithLongDescription();
if (requireTags != null) { query = query.WithTags(requireTags); }
TaskPool.Add(GetWorkshopItemsAsync(query), (task) => { onItemsFound?.Invoke(task.Result); });
TaskPool.Add("GetSubscribedWorkshopItems", GetWorkshopItemsAsync(query), (task) => { onItemsFound?.Invoke(((Task<List<Steamworks.Ugc.Item>>)task).Result); });
}
public static void GetPopularWorkshopItems(Action<IList<Steamworks.Ugc.Item>> onItemsFound, int amount, List<string> requireTags = null)
@@ -582,8 +620,8 @@ namespace Barotrauma.Steam
.WithLongDescription();
if (requireTags != null) query.WithTags(requireTags);
TaskPool.Add(GetWorkshopItemsAsync(query, amount, (item) => !item.IsSubscribed), (task) => {
var entries = task.Result;
TaskPool.Add("GetPopularWorkshopItems", GetWorkshopItemsAsync(query, amount, (item) => !item.IsSubscribed), (task) => {
var entries = ((Task<List<Steamworks.Ugc.Item>>)task).Result;
//count the number of each unique tag
foreach (var item in entries)
@@ -614,7 +652,7 @@ namespace Barotrauma.Steam
}
popularTags.Insert(i, tagCommonnessKVP.Key);
}
onItemsFound?.Invoke(task.Result);
onItemsFound?.Invoke(entries);
});
}
@@ -628,7 +666,7 @@ namespace Barotrauma.Steam
.WithLongDescription();
if (requireTags != null) query.WithTags(requireTags);
TaskPool.Add(GetWorkshopItemsAsync(query), (task) => { onItemsFound?.Invoke(task.Result); });
TaskPool.Add("GetPublishedWorkshopItems", GetWorkshopItemsAsync(query), (task) => { onItemsFound?.Invoke(((Task<List<Steamworks.Ugc.Item>>)task).Result); });
}
private static Dictionary<ulong, Task> ugcSubscriptionTasks;
@@ -678,7 +716,7 @@ namespace Barotrauma.Steam
{
string folderPath = Path.GetDirectoryName(contentPackage.Path);
if (!Directory.Exists(folderPath)) { Directory.CreateDirectory(folderPath); }
itemEditor = Steamworks.Ugc.Editor.CreateCommunityFile()
itemEditor = Steamworks.Ugc.Editor.NewCommunityFile
.WithPublicVisibility()
.ForAppId(AppID)
.WithContent(folderPath);
@@ -700,7 +738,7 @@ namespace Barotrauma.Steam
Directory.CreateDirectory("Mods");
Directory.CreateDirectory(dirPath);
itemEditor = Steamworks.Ugc.Editor.CreateCommunityFile()
itemEditor = Steamworks.Ugc.Editor.NewCommunityFile
#if DEBUG
.WithPrivateVisibility()
#else
@@ -827,6 +865,11 @@ namespace Barotrauma.Steam
DebugConsole.ThrowError("Cannot publish workshop item \"" + item?.Title + "\" - folder not set.");
return null;
}
if (!contentPackage.Files.Any())
{
DebugConsole.ThrowError("Cannot publish workshop item \"" + item?.Title + "\" - no files defined.");
return null;
}
#if DEBUG
item = item?.WithPrivateVisibility();
@@ -944,13 +987,6 @@ namespace Barotrauma.Steam
return false;
}
if (contentPackage.CorePackage && !contentPackage.ContainsRequiredCorePackageFiles(out List<ContentType> missingContentTypes))
{
errorMsg = TextManager.GetWithVariables("ContentPackageMissingCoreFiles", new string[2] { "[packagename]", "[missingfiletypes]" },
new string[2] { contentPackage.Name, string.Join(", ", missingContentTypes) }, new bool[2] { false, true });
return false;
}
Task<string> newTask = null;
lock (modCopiesInProgress)
@@ -963,7 +999,8 @@ namespace Barotrauma.Steam
modCopiesInProgress.Add(item.Value.Id, newTask);
}
TaskPool.Add(newTask,
TaskPool.Add("CopyWorkShopItemAsync",
newTask,
contentPackage,
(task, cp) =>
{
@@ -975,9 +1012,10 @@ namespace Barotrauma.Steam
GameMain.SteamWorkshopScreen?.SetReinstallButtonStatus(item, true, GUI.Style.Red);
return;
}
if (!string.IsNullOrWhiteSpace(task.Result))
string errorMsg = ((Task<string>)task).Result;
if (!string.IsNullOrWhiteSpace(errorMsg))
{
DebugConsole.ThrowError($"Failed to copy \"{item?.Title}\": {task.Result}");
DebugConsole.ThrowError($"Failed to copy \"{item?.Title}\": {errorMsg}");
GameMain.SteamWorkshopScreen?.SetReinstallButtonStatus(item, true, GUI.Style.Red);
return;
}
@@ -1199,7 +1237,7 @@ namespace Barotrauma.Steam
{
if (cp.CorePackage)
{
GameMain.Config.SelectCorePackage(ContentPackage.List.Find(cpp => cpp.CorePackage && !toRemove.Contains(cpp)));
GameMain.Config.AutoSelectCorePackage(toRemove);
}
else
{
@@ -1296,6 +1334,14 @@ namespace Barotrauma.Steam
{
if (!(item?.IsInstalled ?? false)) { return false; }
lock (modCopiesInProgress)
{
if (modCopiesInProgress.ContainsKey(item.Value.Id))
{
return true;
}
}
if (!Directory.Exists(item?.Directory))
{
DebugConsole.ThrowError("Workshop item \"" + item?.Title + "\" has been installed but the install directory cannot be found. Attempting to redownload...");
@@ -1572,7 +1618,7 @@ namespace Barotrauma.Steam
if (type == ContentType.Executable ||
type == ContentType.ServerExecutable)
{
exists |= File.Exists(contentFilePath + ".dll");
exists |= File.Exists(Path.GetFileNameWithoutExtension(contentFilePath) + ".dll");
}
if (exists)
{
@@ -52,6 +52,10 @@ namespace Barotrauma.Networking
}
}
public readonly bool CanDetectDisconnect;
public bool Disconnected { get; private set; }
public static void Create(string deviceName, UInt16? storedBufferID=null)
{
if (Instance != null)
@@ -71,6 +75,8 @@ namespace Barotrauma.Networking
private VoipCapture(string deviceName) : base(GameMain.Client?.ID ?? 0, true, false)
{
Disconnected = false;
VoipConfig.SetupEncoding();
//set up capture device
@@ -121,6 +127,13 @@ namespace Barotrauma.Networking
throw new Exception("Failed to open capture device: " + alError.ToString() + " (AL)");
}
CanDetectDisconnect = Alc.IsExtensionPresent(captureDevice, "ALC_EXT_disconnect");
alcError = Alc.GetError(captureDevice);
if (alcError != Alc.NoError)
{
throw new Exception("Error determining if disconnect can be detected: " + alcError.ToString());
}
Alc.CaptureStart(captureDevice);
alcError = Alc.GetError(captureDevice);
if (alcError != Alc.NoError)
@@ -158,9 +171,27 @@ namespace Barotrauma.Networking
{
Array.Copy(uncompressedBuffer, 0, prevUncompressedBuffer, 0, VoipConfig.BUFFER_SIZE);
Array.Clear(uncompressedBuffer, 0, VoipConfig.BUFFER_SIZE);
while (capturing)
while (capturing && !Disconnected)
{
int alcError;
if (CanDetectDisconnect)
{
Alc.GetInteger(captureDevice, Alc.EnumConnected, out int isConnected);
alcError = Alc.GetError(captureDevice);
if (alcError != Alc.NoError)
{
throw new Exception("Failed to determine if capture device is connected: " + alcError.ToString());
}
if (isConnected == 0)
{
DebugConsole.ThrowError("Capture device has been disconnected. You can select another available device in the settings.");
Disconnected = true;
break;
}
}
Alc.GetInteger(captureDevice, Alc.EnumCaptureSamples, out int sampleCount);
alcError = Alc.GetError(captureDevice);
@@ -112,11 +112,10 @@ namespace Barotrauma
switch (voteType)
{
case VoteType.Sub:
case VoteType.Sub:
SubmarineInfo sub = data as SubmarineInfo;
if (sub == null) { return; }
msg.Write(sub.Name);
msg.Write(sub.EqualityCheckVal);
break;
case VoteType.Mode:
GameModePreset gameMode = data as GameModePreset;
@@ -137,6 +136,25 @@ namespace Barotrauma
if (!(data is bool)) return;
msg.Write((bool)data);
break;
case VoteType.PurchaseAndSwitchSub:
case VoteType.PurchaseSub:
case VoteType.SwitchSub:
if (!VoteRunning)
{
SubmarineInfo voteSub = data as SubmarineInfo;
if (voteSub == null) return;
msg.Write(true);
msg.Write(voteSub.Name);
}
else
{
if (!(data is int)) { return; }
msg.Write(false);
msg.Write((int)data);
}
break;
}
msg.WritePadBits();
@@ -183,6 +201,128 @@ namespace Barotrauma
}
AllowVoteKick = inc.ReadBoolean();
byte subVoteStateByte = inc.ReadByte();
VoteState subVoteState = VoteState.None;
try
{
subVoteState = (VoteState)subVoteStateByte;
}
catch (System.Exception e)
{
DebugConsole.ThrowError("Failed to cast vote type \"" + subVoteStateByte + "\"", e);
}
if (subVoteState != VoteState.None)
{
byte voteTypeByte = inc.ReadByte();
VoteType voteType = VoteType.Unknown;
try
{
voteType = (VoteType)voteTypeByte;
}
catch (System.Exception e)
{
DebugConsole.ThrowError("Failed to cast vote type \"" + voteTypeByte + "\"", e);
}
if (voteType != VoteType.Unknown)
{
byte yesClientCount = inc.ReadByte();
for (int i = 0; i < yesClientCount; i++)
{
byte clientID = inc.ReadByte();
var matchingClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == clientID);
matchingClient?.SetVote(voteType, 2);
}
byte noClientCount = inc.ReadByte();
for (int i = 0; i < noClientCount; i++)
{
byte clientID = inc.ReadByte();
var matchingClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == clientID);
matchingClient?.SetVote(voteType, 1);
}
GameMain.NetworkMember.SubmarineVoteYesCount = yesClientCount;
GameMain.NetworkMember.SubmarineVoteNoCount = noClientCount;
GameMain.NetworkMember.SubmarineVoteMax = inc.ReadByte();
switch (subVoteState)
{
case VoteState.Started:
Client myClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == GameMain.Client.ID);
if (!myClient.InGame)
{
VoteRunning = true;
return;
}
string subName1 = inc.ReadString();
SubmarineInfo info = GameMain.Client.ServerSubmarines.FirstOrDefault(s => s.Name == subName1);
if (info == null)
{
DebugConsole.ThrowError("Failed to find a matching submarine, vote aborted");
return;
}
VoteRunning = true;
byte starterID = inc.ReadByte();
Client starterClient = GameMain.NetworkMember.ConnectedClients.Find(c => c.ID == starterID);
float timeOut = inc.ReadByte();
GameMain.Client.ShowSubmarineChangeVoteInterface(starterClient, info, voteType, timeOut);
break;
case VoteState.Running:
// Nothing specific
break;
case VoteState.Passed:
case VoteState.Failed:
VoteRunning = false;
bool passed = inc.ReadBoolean();
string subName2 = inc.ReadString();
SubmarineInfo subInfo = GameMain.Client.ServerSubmarines.FirstOrDefault(s => s.Name == subName2);
if (subInfo == null)
{
DebugConsole.ThrowError("Failed to find a matching submarine, vote aborted");
return;
}
if (GameMain.Client.VotingInterface != null)
{
GameMain.Client.VotingInterface.EndVote(passed, yesClientCount, noClientCount);
}
else if (GameMain.Client.ConnectedClients.Count > 1)
{
GameMain.NetworkMember.AddChatMessage(VotingInterface.GetSubmarineVoteResultMessage(subInfo, voteType, yesClientCount.ToString(), noClientCount.ToString(), passed), ChatMessageType.Server);
}
if (passed)
{
int deliveryFee = inc.ReadInt16();
switch (voteType)
{
case VoteType.PurchaseAndSwitchSub:
GameMain.GameSession.PurchaseSubmarine(subInfo);
GameMain.GameSession.SwitchSubmarine(subInfo, 0);
break;
case VoteType.PurchaseSub:
GameMain.GameSession.PurchaseSubmarine(subInfo);
break;
case VoteType.SwitchSub:
GameMain.GameSession.SwitchSubmarine(subInfo, deliveryFee);
break;
}
SubmarineSelection.ContentRefreshRequired = true;
}
break;
}
}
}
GameMain.NetworkMember.ConnectedClients.ForEach(c => c.SetVote(VoteType.StartRound, false));
byte readyClientCount = inc.ReadByte();
for (int i = 0; i < readyClientCount; i++)