v0.10.5.1
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Barotrauma.Steam;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -7,12 +8,13 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
partial class BannedPlayer
|
||||
{
|
||||
public BannedPlayer(string name, UInt16 uniqueIdentifier, bool isRangeBan, string ip, ulong steamID)
|
||||
public BannedPlayer(string name, UInt16 uniqueIdentifier, bool isRangeBan, string endPoint, ulong steamID)
|
||||
{
|
||||
this.Name = name;
|
||||
this.EndPoint = endPoint;
|
||||
this.SteamID = steamID;
|
||||
ParseEndPointAsSteamId();
|
||||
this.IsRangeBan = isRangeBan;
|
||||
this.IP = ip;
|
||||
this.UniqueIdentifier = uniqueIdentifier;
|
||||
}
|
||||
}
|
||||
@@ -66,13 +68,13 @@ namespace Barotrauma.Networking
|
||||
RelativeSpacing = 0.02f
|
||||
};
|
||||
|
||||
string ip = bannedPlayer.IP;
|
||||
if (localRangeBans.Contains(bannedPlayer.UniqueIdentifier)) ip = ToRange(ip);
|
||||
string endPoint = bannedPlayer.EndPoint;
|
||||
if (localRangeBans.Contains(bannedPlayer.UniqueIdentifier)) endPoint = ToRange(endPoint);
|
||||
GUITextBlock textBlock = new GUITextBlock(new RectTransform(new Vector2(0.5f, 0.0f), topArea.RectTransform),
|
||||
bannedPlayer.Name + " (" + ip + ")");
|
||||
bannedPlayer.Name + " (" + endPoint + ")");
|
||||
textBlock.RectTransform.MinSize = new Point(textBlock.Rect.Width, 0);
|
||||
|
||||
if (bannedPlayer.IP.IndexOf(".x") <= -1)
|
||||
if (bannedPlayer.EndPoint.IndexOf(".x") <= -1)
|
||||
{
|
||||
var rangeBanButton = new GUIButton(new RectTransform(new Vector2(0.25f, 0.4f), topArea.RectTransform),
|
||||
TextManager.Get("BanRange"), style: "GUIButtonSmall")
|
||||
@@ -156,19 +158,19 @@ namespace Barotrauma.Networking
|
||||
UInt16 uniqueIdentifier = incMsg.ReadUInt16();
|
||||
bool isRangeBan = incMsg.ReadBoolean(); incMsg.ReadPadBits();
|
||||
|
||||
string ip = "";
|
||||
string endPoint = "";
|
||||
UInt64 steamID = 0;
|
||||
if (isOwner)
|
||||
{
|
||||
ip = incMsg.ReadString();
|
||||
endPoint = incMsg.ReadString();
|
||||
steamID = incMsg.ReadUInt64();
|
||||
}
|
||||
else
|
||||
{
|
||||
ip = "IP concealed by host";
|
||||
endPoint = "Endpoint concealed by host";
|
||||
steamID = 0;
|
||||
}
|
||||
bannedPlayers.Add(new BannedPlayer(name, uniqueIdentifier, isRangeBan, ip, steamID));
|
||||
bannedPlayers.Add(new BannedPlayer(name, uniqueIdentifier, isRangeBan, endPoint, steamID));
|
||||
}
|
||||
|
||||
if (banFrame != null)
|
||||
|
||||
@@ -520,11 +520,13 @@ namespace Barotrauma.Networking
|
||||
msgBox.Content.Parent.RectTransform.MinSize = new Point(0, (int)(msgBox.Content.RectTransform.MinSize.Y / msgBox.Content.RectTransform.RelativeSize.Y));
|
||||
|
||||
var okButton = msgBox.Buttons[0];
|
||||
okButton.OnClicked += msgBox.Close;
|
||||
var cancelButton = msgBox.Buttons[1];
|
||||
cancelButton.OnClicked += msgBox.Close;
|
||||
|
||||
okButton.OnClicked += (GUIButton button, object obj) =>
|
||||
{
|
||||
clientPeer.SendPassword(passwordBox.Text);
|
||||
clientPeer?.SendPassword(passwordBox.Text);
|
||||
requiresPw = false;
|
||||
return true;
|
||||
};
|
||||
@@ -855,22 +857,6 @@ namespace Barotrauma.Networking
|
||||
traitorResults.Add(new TraitorMissionResult(inc));
|
||||
}
|
||||
|
||||
if (GameMain.GameSession?.GameMode is CampaignMode mpCampaign)
|
||||
{
|
||||
if (inc.ReadBoolean())
|
||||
{
|
||||
Dictionary<string, int> clientUpgrades = UpgradeManager.GetMetadataLevels(mpCampaign.CampaignMetadata);
|
||||
Dictionary<string, int> serverUpgrades = new Dictionary<string, int>();
|
||||
|
||||
int length = inc.ReadUInt16();
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
serverUpgrades.Add(inc.ReadString(), inc.ReadByte());
|
||||
}
|
||||
UpgradeManager.CompareUpgrades(clientUpgrades, serverUpgrades);
|
||||
}
|
||||
}
|
||||
|
||||
roundInitStatus = RoundInitStatus.Interrupted;
|
||||
CoroutineManager.StartCoroutine(EndGame(endMessage, traitorResults, transitionType), "EndGame");
|
||||
break;
|
||||
@@ -934,7 +920,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
private void ReadStartGameFinalize(IReadMessage inc)
|
||||
{
|
||||
TaskPool.ListTasks(null);
|
||||
TaskPool.ListTasks();
|
||||
ushort contentToPreloadCount = inc.ReadUInt16();
|
||||
List<ContentFile> contentToPreload = new List<ContentFile>();
|
||||
for (int i = 0; i < contentToPreloadCount; i++)
|
||||
@@ -1006,8 +992,19 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
|
||||
private void OnDisconnect()
|
||||
private void OnDisconnect(bool disableReconnect)
|
||||
{
|
||||
CoroutineManager.StopCoroutines("WaitForStartingInfo");
|
||||
reconnectBox?.Close();
|
||||
reconnectBox = null;
|
||||
|
||||
GameMain.Config.RestoreBackupPackages();
|
||||
|
||||
GUI.ClearCursorWait();
|
||||
|
||||
if (disableReconnect) { allowReconnect = false; }
|
||||
if (!this.allowReconnect) { CancelConnect(); }
|
||||
|
||||
if (SteamManager.IsInitialized)
|
||||
{
|
||||
Steamworks.SteamFriends.ClearRichPresence();
|
||||
@@ -1107,8 +1104,9 @@ namespace Barotrauma.Networking
|
||||
|
||||
reconnectBox?.Close();
|
||||
reconnectBox = new GUIMessageBox(
|
||||
TextManager.Get("ConnectionLost"),
|
||||
msg, new string[0]);
|
||||
TextManager.Get("ConnectionLost"), msg,
|
||||
new string[] { TextManager.Get("Cancel") });
|
||||
reconnectBox.Buttons[0].OnClicked += (btn, userdata) => { CancelConnect(); return true; };
|
||||
connected = false;
|
||||
ConnectToServer(serverEndpoint, serverName);
|
||||
}
|
||||
@@ -1385,6 +1383,7 @@ namespace Barotrauma.Networking
|
||||
if (gameMode == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Game mode \"" + modeIdentifier + "\" not found!");
|
||||
roundInitStatus = RoundInitStatus.Interrupted;
|
||||
yield return CoroutineStatus.Failure;
|
||||
}
|
||||
|
||||
@@ -1415,11 +1414,13 @@ namespace Barotrauma.Networking
|
||||
int missionIndex = inc.ReadInt16();
|
||||
if (!GameMain.NetLobbyScreen.TrySelectSub(subName, subHash, GameMain.NetLobbyScreen.SubList))
|
||||
{
|
||||
roundInitStatus = RoundInitStatus.Interrupted;
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
if (!GameMain.NetLobbyScreen.TrySelectSub(shuttleName, shuttleHash, GameMain.NetLobbyScreen.ShuttleList.ListBox))
|
||||
{
|
||||
roundInitStatus = RoundInitStatus.Interrupted;
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
@@ -1448,6 +1449,7 @@ namespace Barotrauma.Networking
|
||||
GameMain.NetLobbyScreen.Select();
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:FailedToSelectSub" + subName, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
roundInitStatus = RoundInitStatus.Interrupted;
|
||||
yield return CoroutineStatus.Failure;
|
||||
}
|
||||
if (GameMain.NetLobbyScreen.SelectedShuttle == null ||
|
||||
@@ -1459,6 +1461,7 @@ namespace Barotrauma.Networking
|
||||
string errorMsg = "Failed to select shuttle \"" + shuttleName + "\" (hash: " + shuttleHash + ").";
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:FailedToSelectShuttle" + shuttleName, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
roundInitStatus = RoundInitStatus.Interrupted;
|
||||
yield return CoroutineStatus.Failure;
|
||||
}
|
||||
|
||||
@@ -1487,6 +1490,7 @@ namespace Barotrauma.Networking
|
||||
gameStarted = true;
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameMain.NetLobbyScreen.Select();
|
||||
roundInitStatus = RoundInitStatus.Interrupted;
|
||||
yield return CoroutineStatus.Failure;
|
||||
}
|
||||
else if (campaign.Map == null)
|
||||
@@ -1495,6 +1499,7 @@ namespace Barotrauma.Networking
|
||||
gameStarted = true;
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameMain.NetLobbyScreen.Select();
|
||||
roundInitStatus = RoundInitStatus.Interrupted;
|
||||
yield return CoroutineStatus.Failure;
|
||||
}
|
||||
|
||||
@@ -1515,6 +1520,11 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
if (GameMain.Client?.ServerSettings?.Voting != null)
|
||||
{
|
||||
GameMain.Client.ServerSettings.Voting.ResetVotes(GameMain.Client.ConnectedClients);
|
||||
}
|
||||
|
||||
if (loadTask != null)
|
||||
{
|
||||
while (!loadTask.IsCompleted && !loadTask.IsFaulted && !loadTask.IsCanceled)
|
||||
@@ -1626,7 +1636,10 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
if (respawnAllowed) { respawnManager = new RespawnManager(this, GameMain.NetLobbyScreen.UsingShuttle ? GameMain.NetLobbyScreen.SelectedShuttle : null); }
|
||||
if (respawnAllowed)
|
||||
{
|
||||
respawnManager = new RespawnManager(this, GameMain.NetLobbyScreen.UsingShuttle && gameMode != GameModePreset.MultiPlayerCampaign ? GameMain.NetLobbyScreen.SelectedShuttle : null);
|
||||
}
|
||||
|
||||
gameStarted = true;
|
||||
ServerSettings.ServerDetailsChanged = true;
|
||||
@@ -1645,6 +1658,17 @@ namespace Barotrauma.Networking
|
||||
|
||||
public IEnumerable<object> EndGame(string endMessage, List<TraitorMissionResult> traitorResults = null, CampaignMode.TransitionType transitionType = CampaignMode.TransitionType.None)
|
||||
{
|
||||
//round starting up, wait for it to finish
|
||||
DateTime timeOut = DateTime.Now + new TimeSpan(0, 0, 60);
|
||||
while (TaskPool.IsTaskRunning("AsyncCampaignStartRound"))
|
||||
{
|
||||
if (DateTime.Now > timeOut)
|
||||
{
|
||||
throw new Exception("Failed to end a round (async campaign round start timed out).");
|
||||
}
|
||||
yield return new WaitForSeconds(1.0f);
|
||||
}
|
||||
|
||||
if (!gameStarted)
|
||||
{
|
||||
GameMain.NetLobbyScreen.Select();
|
||||
@@ -2086,7 +2110,6 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
while ((objHeader = (ServerNetObject)inc.ReadByte()) != ServerNetObject.END_OF_MESSAGE)
|
||||
{
|
||||
bool eventReadFailed = false;
|
||||
switch (objHeader)
|
||||
{
|
||||
case ServerNetObject.SYNC_IDS:
|
||||
@@ -2110,7 +2133,13 @@ namespace Barotrauma.Networking
|
||||
int msgEndPos = (int)(inc.BitPosition + msgLength * 8);
|
||||
|
||||
var entity = Entity.FindEntityByID(id) as IServerSerializable;
|
||||
if (entity != null)
|
||||
if (msgEndPos > inc.LengthBits)
|
||||
{
|
||||
DebugConsole.ThrowError($"Error while reading a position update for the entity \"({entity?.ToString() ?? "null"})\". Message length exceeds the size of the buffer.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (entity != null && (entity is Item || entity is Character || entity is Submarine))
|
||||
{
|
||||
entity.ClientRead(objHeader.Value, inc, sendingTime);
|
||||
}
|
||||
@@ -2127,8 +2156,7 @@ namespace Barotrauma.Networking
|
||||
case ServerNetObject.ENTITY_EVENT_INITIAL:
|
||||
if (!entityEventManager.Read(objHeader.Value, inc, sendingTime, entities))
|
||||
{
|
||||
eventReadFailed = true;
|
||||
break;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case ServerNetObject.CHAT_MESSAGE:
|
||||
@@ -2138,16 +2166,11 @@ namespace Barotrauma.Networking
|
||||
throw new Exception($"Unknown object header \"{objHeader}\"!)");
|
||||
}
|
||||
prevBitLength = inc.BitPosition - prevBitPos;
|
||||
prevByteLength = inc.BytePosition - prevByteLength;
|
||||
prevByteLength = inc.BytePosition - prevBytePos;
|
||||
|
||||
prevObjHeader = objHeader;
|
||||
prevBitPos = inc.BitPosition;
|
||||
prevBytePos = inc.BytePosition;
|
||||
|
||||
if (eventReadFailed)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2618,7 +2641,7 @@ namespace Barotrauma.Networking
|
||||
public void VoteForKick(Client votedClient)
|
||||
{
|
||||
if (votedClient == null) { return; }
|
||||
votedClient.AddKickVote(ConnectedClients.First(c => c.ID == ID));
|
||||
votedClient.AddKickVote(ConnectedClients.FirstOrDefault(c => c.ID == myID));
|
||||
Vote(VoteType.Kick, votedClient);
|
||||
}
|
||||
|
||||
|
||||
+16
-5
@@ -164,6 +164,19 @@ namespace Barotrauma.Networking
|
||||
|
||||
for (int i = 0; i < eventCount; i++)
|
||||
{
|
||||
//16 = entity ID, 8 = msg length
|
||||
if (msg.BitPosition + 16 + 8 > msg.LengthBits)
|
||||
{
|
||||
string errorMsg = $"Error while reading a message from the server. Entity event data exceeds the size of the buffer (current position: {msg.BitPosition}, length: {msg.LengthBits}).";
|
||||
errorMsg += "\nPrevious entities:";
|
||||
for (int j = entities.Count - 1; j >= 0; j--)
|
||||
{
|
||||
errorMsg += "\n" + (entities[j] == null ? "NULL" : entities[j].ToString());
|
||||
}
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
return false;
|
||||
}
|
||||
|
||||
UInt16 thisEventID = (UInt16)(firstEventID + (UInt16)i);
|
||||
UInt16 entityID = msg.ReadUInt16();
|
||||
|
||||
@@ -176,7 +189,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
msg.ReadPadBits();
|
||||
entities.Add(null);
|
||||
if (thisEventID == (UInt16)(lastReceivedID + 1)) lastReceivedID++;
|
||||
if (thisEventID == (UInt16)(lastReceivedID + 1)) { lastReceivedID++; }
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -248,10 +261,8 @@ namespace Barotrauma.Networking
|
||||
errorMsg += "\n" + (entities[j] == null ? "NULL" : entities[j].ToString());
|
||||
}
|
||||
|
||||
if (GameSettings.VerboseLogging)
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to read event for entity \"" + entity.ToString() + "\"!", e);
|
||||
}
|
||||
DebugConsole.ThrowError("Failed to read event for entity \"" + entity.ToString() + "\"!", e);
|
||||
|
||||
GameAnalyticsManager.AddErrorEventOnce("ClientEntityEventManager.Read:ReadFailed" + entity.ToString(),
|
||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
msg.BitPosition = (int)(msgPosition + msgLength * 8);
|
||||
|
||||
+185
-3
@@ -1,13 +1,56 @@
|
||||
using System;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Steam;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
abstract class ClientPeer
|
||||
{
|
||||
protected class ServerContentPackage
|
||||
{
|
||||
public string Name;
|
||||
public string Hash;
|
||||
public UInt64 WorkshopId;
|
||||
|
||||
public ContentPackage RegularPackage
|
||||
{
|
||||
get
|
||||
{
|
||||
return ContentPackage.RegularPackages.Find(p => p.MD5hash.Hash.Equals(Hash));
|
||||
}
|
||||
}
|
||||
|
||||
public ContentPackage CorePackage
|
||||
{
|
||||
get
|
||||
{
|
||||
return ContentPackage.CorePackages.Find(p => p.MD5hash.Hash.Equals(Hash));
|
||||
}
|
||||
}
|
||||
|
||||
public ServerContentPackage(string name, string hash, UInt64 workshopId)
|
||||
{
|
||||
Name = name;
|
||||
Hash = hash;
|
||||
WorkshopId = workshopId;
|
||||
}
|
||||
}
|
||||
|
||||
protected string GetPackageStr(ContentPackage contentPackage)
|
||||
{
|
||||
return "\"" + contentPackage.Name + "\" (hash " + contentPackage.MD5hash.ShortHash + ")";
|
||||
}
|
||||
protected string GetPackageStr(ServerContentPackage contentPackage)
|
||||
{
|
||||
return "\"" + contentPackage.Name + "\" (hash " + Md5Hash.GetShortHash(contentPackage.Hash) + ")";
|
||||
}
|
||||
|
||||
public delegate void MessageCallback(IReadMessage message);
|
||||
public delegate void DisconnectCallback();
|
||||
public delegate void DisconnectCallback(bool disableReconnect);
|
||||
public delegate void DisconnectMessageCallback(string message);
|
||||
public delegate void PasswordCallback(int salt, int retries);
|
||||
public delegate void InitializationCompleteCallback();
|
||||
@@ -25,11 +68,150 @@ namespace Barotrauma.Networking
|
||||
public NetworkConnection ServerConnection { get; protected set; }
|
||||
|
||||
public abstract void Start(object endPoint, int ownerKey);
|
||||
public abstract void Close(string msg = null);
|
||||
public abstract void Close(string msg = null, bool disableReconnect = false);
|
||||
public abstract void Update(float deltaTime);
|
||||
public abstract void Send(IWriteMessage msg, DeliveryMethod deliveryMethod);
|
||||
public abstract void SendPassword(string password);
|
||||
|
||||
protected abstract void SendMsgInternal(DeliveryMethod deliveryMethod, IWriteMessage msg);
|
||||
|
||||
protected ConnectionInitialization initializationStep;
|
||||
protected bool contentPackageOrderReceived;
|
||||
protected int ownerKey = 0;
|
||||
protected int passwordSalt;
|
||||
protected Steamworks.AuthTicket steamAuthTicket;
|
||||
protected void ReadConnectionInitializationStep(IReadMessage inc)
|
||||
{
|
||||
ConnectionInitialization step = (ConnectionInitialization)inc.ReadByte();
|
||||
|
||||
IWriteMessage outMsg;
|
||||
|
||||
switch (step)
|
||||
{
|
||||
case ConnectionInitialization.SteamTicketAndVersion:
|
||||
if (initializationStep != ConnectionInitialization.SteamTicketAndVersion) { return; }
|
||||
outMsg = new WriteOnlyMessage();
|
||||
outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep);
|
||||
outMsg.Write((byte)ConnectionInitialization.SteamTicketAndVersion);
|
||||
outMsg.Write(Name);
|
||||
outMsg.Write(ownerKey);
|
||||
outMsg.Write(SteamManager.GetSteamID());
|
||||
if (steamAuthTicket == null)
|
||||
{
|
||||
outMsg.Write((UInt16)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
outMsg.Write((UInt16)steamAuthTicket.Data.Length);
|
||||
outMsg.Write(steamAuthTicket.Data, 0, steamAuthTicket.Data.Length);
|
||||
}
|
||||
outMsg.Write(GameMain.Version.ToString());
|
||||
outMsg.Write(GameMain.Config.Language);
|
||||
|
||||
SendMsgInternal(DeliveryMethod.Reliable, outMsg);
|
||||
break;
|
||||
case ConnectionInitialization.ContentPackageOrder:
|
||||
if (initializationStep == ConnectionInitialization.SteamTicketAndVersion ||
|
||||
initializationStep == ConnectionInitialization.Password) { initializationStep = ConnectionInitialization.ContentPackageOrder; }
|
||||
if (initializationStep != ConnectionInitialization.ContentPackageOrder) { return; }
|
||||
outMsg = new WriteOnlyMessage();
|
||||
outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep);
|
||||
outMsg.Write((byte)ConnectionInitialization.ContentPackageOrder);
|
||||
|
||||
string serverName = inc.ReadString();
|
||||
|
||||
UInt32 cpCount = inc.ReadVariableUInt32();
|
||||
ServerContentPackage corePackage = null;
|
||||
List<ServerContentPackage> regularPackages = new List<ServerContentPackage>();
|
||||
List<ServerContentPackage> missingPackages = new List<ServerContentPackage>();
|
||||
for (int i = 0; i < cpCount; i++)
|
||||
{
|
||||
string name = inc.ReadString();
|
||||
string hash = inc.ReadString();
|
||||
UInt64 workshopId = inc.ReadUInt64();
|
||||
var pkg = new ServerContentPackage(name, hash, workshopId);
|
||||
if (pkg.CorePackage != null)
|
||||
{
|
||||
corePackage = pkg;
|
||||
}
|
||||
else if (pkg.RegularPackage != null)
|
||||
{
|
||||
regularPackages.Add(pkg);
|
||||
}
|
||||
else
|
||||
{
|
||||
missingPackages.Add(pkg);
|
||||
}
|
||||
}
|
||||
|
||||
if (missingPackages.Count > 0)
|
||||
{
|
||||
var nonDownloadable = missingPackages.Where(p => p.WorkshopId == 0);
|
||||
|
||||
if (nonDownloadable.Any())
|
||||
{
|
||||
string disconnectMsg;
|
||||
if (nonDownloadable.Count() == 1)
|
||||
{
|
||||
disconnectMsg = $"DisconnectMessage.MissingContentPackage~[missingcontentpackage]={GetPackageStr(missingPackages[0])}";
|
||||
}
|
||||
else
|
||||
{
|
||||
List<string> packageStrs = new List<string>();
|
||||
nonDownloadable.ForEach(cp => packageStrs.Add(GetPackageStr(cp)));
|
||||
disconnectMsg = $"DisconnectMessage.MissingContentPackages~[missingcontentpackages]={string.Join(", ", packageStrs)}";
|
||||
}
|
||||
Close(disconnectMsg, disableReconnect: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Close(disableReconnect: true);
|
||||
|
||||
string missingModNames = "\n- " + string.Join("\n\n- ", missingPackages.Select(p => GetPackageStr(p))) + "\n\n";
|
||||
|
||||
var msgBox = new GUIMessageBox(
|
||||
TextManager.Get("WorkshopItemDownloadTitle"),
|
||||
TextManager.GetWithVariable("WorkshopItemDownloadPrompt", "[items]", missingModNames),
|
||||
new string[] { TextManager.Get("Yes"), TextManager.Get("No") });
|
||||
msgBox.Buttons[0].OnClicked = (yesBtn, userdata) =>
|
||||
{
|
||||
GameMain.ServerListScreen.Select();
|
||||
GameMain.ServerListScreen.DownloadWorkshopItems(missingPackages.Select(p => p.WorkshopId), serverName, ServerConnection.EndPointString);
|
||||
return true;
|
||||
};
|
||||
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
||||
msgBox.Buttons[1].OnClicked = msgBox.Close;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!contentPackageOrderReceived)
|
||||
{
|
||||
GameMain.Config.SwapPackages(corePackage.CorePackage, regularPackages.Select(p => p.RegularPackage).ToList());
|
||||
contentPackageOrderReceived = true;
|
||||
}
|
||||
|
||||
SendMsgInternal(DeliveryMethod.Reliable, outMsg);
|
||||
break;
|
||||
case ConnectionInitialization.Password:
|
||||
if (initializationStep == ConnectionInitialization.SteamTicketAndVersion) { initializationStep = ConnectionInitialization.Password; }
|
||||
if (initializationStep != ConnectionInitialization.Password) { return; }
|
||||
bool incomingSalt = inc.ReadBoolean(); inc.ReadPadBits();
|
||||
int retries = 0;
|
||||
if (incomingSalt)
|
||||
{
|
||||
passwordSalt = inc.ReadInt32();
|
||||
}
|
||||
else
|
||||
{
|
||||
retries = inc.ReadInt32();
|
||||
}
|
||||
OnRequestPassword?.Invoke(passwordSalt, retries);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
public abstract void ForceTimeOut();
|
||||
#endif
|
||||
|
||||
+15
-101
@@ -14,11 +14,6 @@ namespace Barotrauma.Networking
|
||||
private NetClient netClient;
|
||||
private NetPeerConfiguration netPeerConfiguration;
|
||||
|
||||
private ConnectionInitialization initializationStep;
|
||||
private bool contentPackageOrderReceived;
|
||||
private int ownerKey;
|
||||
private int passwordSalt;
|
||||
private Steamworks.AuthTicket steamAuthTicket;
|
||||
List<NetIncomingMessage> incomingLidgrenMessages;
|
||||
|
||||
public LidgrenClientPeer(string name)
|
||||
@@ -128,7 +123,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (isConnectionInitializationStep && initializationStep != ConnectionInitialization.Success)
|
||||
{
|
||||
ReadConnectionInitializationStep(inc);
|
||||
ReadConnectionInitializationStep(new ReadWriteMessage(inc.Data, (int)inc.Position, inc.LengthBits, false));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -158,99 +153,6 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
private void ReadConnectionInitializationStep(NetIncomingMessage inc)
|
||||
{
|
||||
if (!isActive) { return; }
|
||||
|
||||
ConnectionInitialization step = (ConnectionInitialization)inc.ReadByte();
|
||||
//Console.WriteLine(step + " " + initializationStep);
|
||||
NetOutgoingMessage outMsg; NetSendResult result;
|
||||
|
||||
switch (step)
|
||||
{
|
||||
case ConnectionInitialization.SteamTicketAndVersion:
|
||||
if (initializationStep != ConnectionInitialization.SteamTicketAndVersion) { return; }
|
||||
outMsg = netClient.CreateMessage();
|
||||
outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep);
|
||||
outMsg.Write((byte)ConnectionInitialization.SteamTicketAndVersion);
|
||||
outMsg.Write(Name);
|
||||
outMsg.Write(ownerKey);
|
||||
outMsg.Write(SteamManager.GetSteamID());
|
||||
if (steamAuthTicket == null)
|
||||
{
|
||||
outMsg.Write((UInt16)0);
|
||||
}
|
||||
else
|
||||
{
|
||||
outMsg.Write((UInt16)steamAuthTicket.Data.Length);
|
||||
outMsg.Write(steamAuthTicket.Data, 0, steamAuthTicket.Data.Length);
|
||||
}
|
||||
|
||||
outMsg.Write(GameMain.Version.ToString());
|
||||
|
||||
IEnumerable<ContentPackage> mpContentPackages = GameMain.SelectedPackages.Where(cp => cp.HasMultiplayerIncompatibleContent);
|
||||
outMsg.WriteVariableInt32(mpContentPackages.Count());
|
||||
foreach (ContentPackage contentPackage in mpContentPackages)
|
||||
{
|
||||
outMsg.Write(contentPackage.Name);
|
||||
outMsg.Write(contentPackage.MD5hash.Hash);
|
||||
}
|
||||
|
||||
result = netClient.SendMessage(outMsg, NetDeliveryMethod.ReliableUnordered);
|
||||
if (result != NetSendResult.Queued && result != NetSendResult.Sent)
|
||||
{
|
||||
DebugConsole.NewMessage("Failed to send "+initializationStep.ToString()+" message to host: " + result);
|
||||
}
|
||||
break;
|
||||
case ConnectionInitialization.ContentPackageOrder:
|
||||
if (initializationStep == ConnectionInitialization.SteamTicketAndVersion ||
|
||||
initializationStep == ConnectionInitialization.Password) { initializationStep = ConnectionInitialization.ContentPackageOrder; }
|
||||
if (initializationStep != ConnectionInitialization.ContentPackageOrder) { return; }
|
||||
outMsg = netClient.CreateMessage();
|
||||
outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep);
|
||||
outMsg.Write((byte)ConnectionInitialization.ContentPackageOrder);
|
||||
|
||||
Int32 cpCount = inc.ReadVariableInt32();
|
||||
List<ContentPackage> serverContentPackages = new List<ContentPackage>();
|
||||
for (int i = 0; i < cpCount; i++)
|
||||
{
|
||||
string hash = inc.ReadString();
|
||||
serverContentPackages.Add(GameMain.Config.SelectedContentPackages.Find(cp => cp.MD5hash.Hash == hash));
|
||||
}
|
||||
|
||||
if (!contentPackageOrderReceived)
|
||||
{
|
||||
GameMain.Config.ReorderSelectedContentPackages(cp => serverContentPackages.Contains(cp) ?
|
||||
serverContentPackages.IndexOf(cp) :
|
||||
serverContentPackages.Count + GameMain.Config.SelectedContentPackages.IndexOf(cp));
|
||||
contentPackageOrderReceived = true;
|
||||
}
|
||||
|
||||
result = netClient.SendMessage(outMsg, NetDeliveryMethod.ReliableUnordered);
|
||||
if (result != NetSendResult.Queued && result != NetSendResult.Sent)
|
||||
{
|
||||
DebugConsole.NewMessage("Failed to send " + initializationStep.ToString() + " message to host: " + result);
|
||||
}
|
||||
|
||||
break;
|
||||
case ConnectionInitialization.Password:
|
||||
if (initializationStep == ConnectionInitialization.SteamTicketAndVersion) { initializationStep = ConnectionInitialization.Password; }
|
||||
if (initializationStep != ConnectionInitialization.Password) { return; }
|
||||
bool incomingSalt = inc.ReadBoolean(); inc.ReadPadBits();
|
||||
int retries = 0;
|
||||
if (incomingSalt)
|
||||
{
|
||||
passwordSalt = inc.ReadInt32();
|
||||
}
|
||||
else
|
||||
{
|
||||
retries = inc.ReadInt32();
|
||||
}
|
||||
OnRequestPassword?.Invoke(passwordSalt, retries);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void SendPassword(string password)
|
||||
{
|
||||
if (!isActive) { return; }
|
||||
@@ -269,7 +171,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
public override void Close(string msg = null)
|
||||
public override void Close(string msg = null, bool disableReconnect = false)
|
||||
{
|
||||
if (!isActive) { return; }
|
||||
|
||||
@@ -278,7 +180,7 @@ namespace Barotrauma.Networking
|
||||
netClient.Shutdown(msg ?? TextManager.Get("Disconnecting"));
|
||||
netClient = null;
|
||||
steamAuthTicket?.Cancel(); steamAuthTicket = null;
|
||||
OnDisconnect?.Invoke();
|
||||
OnDisconnect?.Invoke(disableReconnect);
|
||||
}
|
||||
|
||||
public override void Send(IWriteMessage msg, DeliveryMethod deliveryMethod)
|
||||
@@ -320,6 +222,18 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
protected override void SendMsgInternal(DeliveryMethod deliveryMethod, IWriteMessage msg)
|
||||
{
|
||||
NetOutgoingMessage lidgrenMsg = netClient.CreateMessage();
|
||||
lidgrenMsg.Write(msg.Buffer, 0, msg.LengthBytes);
|
||||
|
||||
NetSendResult result = netClient.SendMessage(lidgrenMsg, NetDeliveryMethod.ReliableUnordered);
|
||||
if (result != NetSendResult.Queued && result != NetSendResult.Sent)
|
||||
{
|
||||
DebugConsole.NewMessage("Failed to send message to host: " + result + "\n" + Environment.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
public override void ForceTimeOut()
|
||||
{
|
||||
|
||||
+32
-92
@@ -12,10 +12,6 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
private bool isActive;
|
||||
private UInt64 hostSteamId;
|
||||
private ConnectionInitialization initializationStep;
|
||||
private bool contentPackageOrderReceived;
|
||||
private int passwordSalt;
|
||||
private Steamworks.AuthTicket steamAuthTicket;
|
||||
private double timeout;
|
||||
private double heartbeatTimer;
|
||||
private double connectionStatusTimer;
|
||||
@@ -89,6 +85,7 @@ namespace Barotrauma.Networking
|
||||
Steamworks.SteamNetworking.AcceptP2PSessionWithUser(steamId);
|
||||
}
|
||||
else if (initializationStep != ConnectionInitialization.Password &&
|
||||
initializationStep != ConnectionInitialization.ContentPackageOrder &&
|
||||
initializationStep != ConnectionInitialization.Success)
|
||||
{
|
||||
DebugConsole.ThrowError($"Connection from incorrect SteamID was rejected: "+
|
||||
@@ -105,7 +102,7 @@ namespace Barotrauma.Networking
|
||||
OnDisconnectMessageReceived?.Invoke($"SteamP2P connection failed: {error}");
|
||||
}
|
||||
|
||||
private void OnP2PData(ulong steamId, byte[] data, int dataLength, int channel)
|
||||
private void OnP2PData(ulong steamId, byte[] data, int dataLength)
|
||||
{
|
||||
if (!isActive) { return; }
|
||||
if (steamId != hostSteamId) { return; }
|
||||
@@ -165,6 +162,7 @@ namespace Barotrauma.Networking
|
||||
heartbeatTimer -= deltaTime;
|
||||
|
||||
if (initializationStep != ConnectionInitialization.Password &&
|
||||
initializationStep != ConnectionInitialization.ContentPackageOrder &&
|
||||
initializationStep != ConnectionInitialization.Success)
|
||||
{
|
||||
connectionStatusTimer -= deltaTime;
|
||||
@@ -194,7 +192,7 @@ namespace Barotrauma.Networking
|
||||
var packet = Steamworks.SteamNetworking.ReadP2PPacket();
|
||||
if (packet.HasValue)
|
||||
{
|
||||
OnP2PData(packet?.SteamId ?? 0, packet?.Data, packet?.Data.Length ?? 0, 0);
|
||||
OnP2PData(packet?.SteamId ?? 0, packet?.Data, packet?.Data.Length ?? 0);
|
||||
receivedBytes += packet?.Data.Length ?? 0;
|
||||
}
|
||||
}
|
||||
@@ -249,88 +247,6 @@ namespace Barotrauma.Networking
|
||||
incomingDataMessages.Clear();
|
||||
}
|
||||
|
||||
private void ReadConnectionInitializationStep(IReadMessage inc)
|
||||
{
|
||||
if (!isActive) { return; }
|
||||
|
||||
ConnectionInitialization step = (ConnectionInitialization)inc.ReadByte();
|
||||
|
||||
IWriteMessage outMsg;
|
||||
|
||||
//DebugConsole.NewMessage(step + " " + initializationStep);
|
||||
switch (step)
|
||||
{
|
||||
case ConnectionInitialization.SteamTicketAndVersion:
|
||||
if (initializationStep != ConnectionInitialization.SteamTicketAndVersion) { return; }
|
||||
outMsg = new WriteOnlyMessage();
|
||||
outMsg.Write((byte)DeliveryMethod.Reliable);
|
||||
outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep);
|
||||
outMsg.Write((byte)ConnectionInitialization.SteamTicketAndVersion);
|
||||
outMsg.Write(Name);
|
||||
outMsg.Write(SteamManager.GetSteamID());
|
||||
outMsg.Write((UInt16)steamAuthTicket.Data.Length);
|
||||
outMsg.Write(steamAuthTicket.Data, 0, steamAuthTicket.Data.Length);
|
||||
|
||||
outMsg.Write(GameMain.Version.ToString());
|
||||
|
||||
IEnumerable<ContentPackage> mpContentPackages = GameMain.SelectedPackages.Where(cp => cp.HasMultiplayerIncompatibleContent);
|
||||
outMsg.WriteVariableUInt32((UInt32)mpContentPackages.Count());
|
||||
foreach (ContentPackage contentPackage in mpContentPackages)
|
||||
{
|
||||
outMsg.Write(contentPackage.Name);
|
||||
outMsg.Write(contentPackage.MD5hash.Hash);
|
||||
}
|
||||
|
||||
heartbeatTimer = 5.0;
|
||||
Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable);
|
||||
sentBytes += outMsg.LengthBytes;
|
||||
break;
|
||||
case ConnectionInitialization.ContentPackageOrder:
|
||||
if (initializationStep == ConnectionInitialization.SteamTicketAndVersion ||
|
||||
initializationStep == ConnectionInitialization.Password) { initializationStep = ConnectionInitialization.ContentPackageOrder; }
|
||||
if (initializationStep != ConnectionInitialization.ContentPackageOrder) { return; }
|
||||
outMsg = new WriteOnlyMessage();
|
||||
outMsg.Write((byte)DeliveryMethod.Reliable);
|
||||
outMsg.Write((byte)PacketHeader.IsConnectionInitializationStep);
|
||||
outMsg.Write((byte)ConnectionInitialization.ContentPackageOrder);
|
||||
|
||||
UInt32 cpCount = inc.ReadVariableUInt32();
|
||||
List<ContentPackage> serverContentPackages = new List<ContentPackage>();
|
||||
for (int i = 0; i < cpCount; i++)
|
||||
{
|
||||
string hash = inc.ReadString();
|
||||
serverContentPackages.Add(GameMain.Config.SelectedContentPackages.Find(cp => cp.MD5hash.Hash == hash));
|
||||
}
|
||||
|
||||
if (!contentPackageOrderReceived)
|
||||
{
|
||||
GameMain.Config.ReorderSelectedContentPackages(cp => serverContentPackages.Contains(cp) ?
|
||||
serverContentPackages.IndexOf(cp) :
|
||||
serverContentPackages.Count + GameMain.Config.SelectedContentPackages.IndexOf(cp));
|
||||
contentPackageOrderReceived = true;
|
||||
}
|
||||
|
||||
Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, outMsg.Buffer, outMsg.LengthBytes, 0, Steamworks.P2PSend.Reliable);
|
||||
sentBytes += outMsg.LengthBytes;
|
||||
break;
|
||||
case ConnectionInitialization.Password:
|
||||
if (initializationStep == ConnectionInitialization.SteamTicketAndVersion) { initializationStep = ConnectionInitialization.Password; }
|
||||
if (initializationStep != ConnectionInitialization.Password) { return; }
|
||||
bool incomingSalt = inc.ReadBoolean(); inc.ReadPadBits();
|
||||
int retries = 0;
|
||||
if (incomingSalt)
|
||||
{
|
||||
passwordSalt = inc.ReadInt32();
|
||||
}
|
||||
else
|
||||
{
|
||||
retries = inc.ReadInt32();
|
||||
}
|
||||
OnRequestPassword?.Invoke(passwordSalt, retries);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Send(IWriteMessage msg, DeliveryMethod deliveryMethod)
|
||||
{
|
||||
if (!isActive) { return; }
|
||||
@@ -339,8 +255,7 @@ namespace Barotrauma.Networking
|
||||
buf[0] = (byte)deliveryMethod;
|
||||
|
||||
byte[] bufAux = new byte[msg.LengthBytes];
|
||||
bool isCompressed; int length;
|
||||
msg.PrepareForSending(ref bufAux, out isCompressed, out length);
|
||||
msg.PrepareForSending(ref bufAux, out bool isCompressed, out int length);
|
||||
|
||||
buf[1] = (byte)(isCompressed ? PacketHeader.IsCompressed : PacketHeader.None);
|
||||
|
||||
@@ -426,7 +341,7 @@ namespace Barotrauma.Networking
|
||||
sentBytes += outMsg.LengthBytes;
|
||||
}
|
||||
|
||||
public override void Close(string msg = null)
|
||||
public override void Close(string msg = null, bool disableReconnect = false)
|
||||
{
|
||||
if (!isActive) { return; }
|
||||
|
||||
@@ -451,7 +366,7 @@ namespace Barotrauma.Networking
|
||||
steamAuthTicket?.Cancel(); steamAuthTicket = null;
|
||||
hostSteamId = 0;
|
||||
|
||||
OnDisconnect?.Invoke();
|
||||
OnDisconnect?.Invoke(disableReconnect);
|
||||
}
|
||||
|
||||
~SteamP2PClientPeer()
|
||||
@@ -460,6 +375,31 @@ namespace Barotrauma.Networking
|
||||
Close();
|
||||
}
|
||||
|
||||
protected override void SendMsgInternal(DeliveryMethod deliveryMethod, IWriteMessage msg)
|
||||
{
|
||||
Steamworks.P2PSend sendType;
|
||||
switch (deliveryMethod)
|
||||
{
|
||||
case DeliveryMethod.Reliable:
|
||||
case DeliveryMethod.ReliableOrdered:
|
||||
//the documentation seems to suggest that the Reliable send type
|
||||
//enforces packet order (TODO: verify)
|
||||
sendType = Steamworks.P2PSend.Reliable;
|
||||
break;
|
||||
default:
|
||||
sendType = Steamworks.P2PSend.Unreliable;
|
||||
break;
|
||||
}
|
||||
|
||||
IWriteMessage msgToSend = new WriteOnlyMessage();
|
||||
msgToSend.Write((byte)deliveryMethod);
|
||||
msgToSend.Write(msg.Buffer, 0, msg.LengthBytes);
|
||||
|
||||
heartbeatTimer = 5.0;
|
||||
Steamworks.SteamNetworking.SendP2PPacket(hostSteamId, msgToSend.Buffer, msgToSend.LengthBytes, 0, sendType);
|
||||
sentBytes += msg.LengthBytes;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
public override void ForceTimeOut()
|
||||
{
|
||||
|
||||
+12
-8
@@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using Barotrauma.Steam;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using Barotrauma.Steam;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
@@ -12,7 +10,6 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
private bool isActive;
|
||||
|
||||
private ConnectionInitialization initializationStep;
|
||||
private readonly UInt64 selfSteamID;
|
||||
|
||||
private long sentBytes, receivedBytes;
|
||||
@@ -61,7 +58,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
initializationStep = ConnectionInitialization.SteamTicketAndVersion;
|
||||
|
||||
ServerConnection = new PipeConnection();
|
||||
ServerConnection = new PipeConnection(selfSteamID);
|
||||
ServerConnection.Status = NetworkConnectionStatus.Connected;
|
||||
|
||||
remotePeers = new List<RemotePeer>();
|
||||
@@ -161,6 +158,7 @@ namespace Barotrauma.Networking
|
||||
remotePeer.Authenticating = true;
|
||||
|
||||
authMsg.ReadString(); //skip name
|
||||
authMsg.ReadInt32(); //skip owner key
|
||||
authMsg.ReadUInt64(); //skip steamid
|
||||
UInt16 ticketLength = authMsg.ReadUInt16();
|
||||
byte[] ticket = authMsg.ReadBytes(ticketLength);
|
||||
@@ -395,7 +393,7 @@ namespace Barotrauma.Networking
|
||||
return; //owner doesn't send passwords
|
||||
}
|
||||
|
||||
public override void Close(string msg = null)
|
||||
public override void Close(string msg = null, bool disableReconnect = false)
|
||||
{
|
||||
if (!isActive) { return; }
|
||||
|
||||
@@ -415,7 +413,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
ChildServerRelay.ClosePipes();
|
||||
|
||||
OnDisconnect?.Invoke();
|
||||
OnDisconnect?.Invoke(disableReconnect);
|
||||
|
||||
SteamManager.LeaveLobby();
|
||||
Steamworks.SteamNetworking.ResetActions();
|
||||
@@ -445,6 +443,12 @@ namespace Barotrauma.Networking
|
||||
Close();
|
||||
}
|
||||
|
||||
protected override void SendMsgInternal(DeliveryMethod deliveryMethod, IWriteMessage msg)
|
||||
{
|
||||
//not currently used by SteamP2POwnerPeer
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
public override void ForceTimeOut()
|
||||
{
|
||||
|
||||
@@ -73,26 +73,25 @@ namespace Barotrauma.Networking
|
||||
get;
|
||||
private set;
|
||||
} = new List<string>();
|
||||
public List<string> ContentPackageWorkshopUrls
|
||||
public List<ulong> ContentPackageWorkshopIds
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
} = new List<string>();
|
||||
} = new List<ulong>();
|
||||
|
||||
public bool ContentPackagesMatch(IEnumerable<ContentPackage> myContentPackages)
|
||||
public bool ContentPackagesMatch()
|
||||
{
|
||||
var myContentPackages = ContentPackage.AllPackages;
|
||||
//make sure we have all the packages the server requires
|
||||
foreach (string hash in ContentPackageHashes)
|
||||
if (ContentPackageHashes.Count != ContentPackageWorkshopIds.Count) { return false; }
|
||||
for (int i = 0; i < ContentPackageWorkshopIds.Count; i++)
|
||||
{
|
||||
if (!myContentPackages.Any(myPackage => myPackage.MD5hash.Hash == hash)) { return false; }
|
||||
}
|
||||
|
||||
//make sure the server isn't missing any of our packages that cause multiplayer incompatibility
|
||||
foreach (ContentPackage myPackage in myContentPackages)
|
||||
{
|
||||
if (myPackage.HasMultiplayerIncompatibleContent)
|
||||
string hash = ContentPackageHashes[i];
|
||||
UInt64 id = ContentPackageWorkshopIds[i];
|
||||
if (!myContentPackages.Any(myPackage => myPackage.MD5hash.Hash == hash))
|
||||
{
|
||||
if (!ContentPackageHashes.Any(hash => hash == myPackage.MD5hash.Hash)) { return false; }
|
||||
if (myContentPackages.Any(p => p.SteamWorkshopId == id)) { return false; }
|
||||
if (id == 0) { return false; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,19 +144,22 @@ namespace Barotrauma.Networking
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), previewContainer.RectTransform),
|
||||
TextManager.AddPunctuation(':', TextManager.Get("ServerListVersion"), string.IsNullOrEmpty(GameVersion) ? TextManager.Get("Unknown") : GameVersion));
|
||||
|
||||
PlayStyle playStyle = PlayStyle ?? Networking.PlayStyle.Serious;
|
||||
bool hidePlaystyleBanner = previewContainer.Rect.Height < 380 || !PlayStyle.HasValue;
|
||||
if (!hidePlaystyleBanner)
|
||||
{
|
||||
PlayStyle playStyle = PlayStyle ?? Networking.PlayStyle.Serious;
|
||||
Sprite playStyleBannerSprite = ServerListScreen.PlayStyleBanners[(int)playStyle];
|
||||
float playStyleBannerAspectRatio = playStyleBannerSprite.SourceRect.Width / playStyleBannerSprite.SourceRect.Height;
|
||||
var playStyleBanner = new GUIImage(new RectTransform(new Point(previewContainer.Rect.Width, (int)(previewContainer.Rect.Width / playStyleBannerAspectRatio)), previewContainer.RectTransform),
|
||||
playStyleBannerSprite, null, true);
|
||||
|
||||
Sprite playStyleBannerSprite = ServerListScreen.PlayStyleBanners[(int)playStyle];
|
||||
float playStyleBannerAspectRatio = playStyleBannerSprite.SourceRect.Width / playStyleBannerSprite.SourceRect.Height;
|
||||
var playStyleBanner = new GUIImage(new RectTransform(new Point(previewContainer.Rect.Width, (int)(previewContainer.Rect.Width / playStyleBannerAspectRatio)), previewContainer.RectTransform),
|
||||
playStyleBannerSprite, null, true);
|
||||
|
||||
var playStyleName = new GUITextBlock(new RectTransform(new Vector2(0.15f, 0.0f), playStyleBanner.RectTransform) { RelativeOffset = new Vector2(0.01f, 0.06f) },
|
||||
TextManager.AddPunctuation(':', TextManager.Get("serverplaystyle"), TextManager.Get("servertag."+ playStyle)), textColor: Color.White,
|
||||
font: GUI.SmallFont, textAlignment: Alignment.Center,
|
||||
color: ServerListScreen.PlayStyleColors[(int)playStyle], style: "GUISlopedHeader");
|
||||
playStyleName.RectTransform.NonScaledSize = (playStyleName.Font.MeasureString(playStyleName.Text) + new Vector2(20, 5) * GUI.Scale).ToPoint();
|
||||
playStyleName.RectTransform.IsFixedSize = true;
|
||||
var playStyleName = new GUITextBlock(new RectTransform(new Vector2(0.15f, 0.0f), playStyleBanner.RectTransform) { RelativeOffset = new Vector2(0.01f, 0.06f) },
|
||||
TextManager.AddPunctuation(':', TextManager.Get("serverplaystyle"), TextManager.Get("servertag."+ playStyle)), textColor: Color.White,
|
||||
font: GUI.SmallFont, textAlignment: Alignment.Center,
|
||||
color: ServerListScreen.PlayStyleColors[(int)playStyle], style: "GUISlopedHeader");
|
||||
playStyleName.RectTransform.NonScaledSize = (playStyleName.Font.MeasureString(playStyleName.Text) + new Vector2(20, 5) * GUI.Scale).ToPoint();
|
||||
playStyleName.RectTransform.IsFixedSize = true;
|
||||
}
|
||||
|
||||
var content = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.6f), previewContainer.RectTransform))
|
||||
{
|
||||
@@ -207,8 +209,13 @@ namespace Barotrauma.Networking
|
||||
TextManager.Get(string.IsNullOrEmpty(GameMode) ? "Unknown" : "GameMode." + GameMode, returnNull: true) ?? GameMode,
|
||||
textAlignment: Alignment.Right);
|
||||
|
||||
/*var traitors = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), bodyContainer.RectTransform), TextManager.Get("Traitors"));
|
||||
new GUITextBlock(new RectTransform(Vector2.One, traitors.RectTransform), TextManager.Get(!TraitorsEnabled.HasValue ? "Unknown" : TraitorsEnabled.Value.ToString()), textAlignment: Alignment.Right);*/
|
||||
GUITextBlock playStyleText = null;
|
||||
if (hidePlaystyleBanner && PlayStyle.HasValue)
|
||||
{
|
||||
PlayStyle playStyle = PlayStyle.Value;
|
||||
playStyleText = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), content.RectTransform), TextManager.Get("serverplaystyle"));
|
||||
new GUITextBlock(new RectTransform(Vector2.One, playStyleText.RectTransform), TextManager.Get("servertag." + playStyle), textAlignment: Alignment.Right);
|
||||
}
|
||||
|
||||
var subSelection = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), content.RectTransform), TextManager.Get("ServerListSubSelection"));
|
||||
new GUITextBlock(new RectTransform(Vector2.One, subSelection.RectTransform), TextManager.Get(!SubSelectionMode.HasValue ? "Unknown" : SubSelectionMode.Value.ToString()), textAlignment: Alignment.Right);
|
||||
@@ -222,6 +229,10 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
gameMode.Font = subSelection.Font = modeSelection.Font = GUI.SmallFont;
|
||||
gameMode.GetChild<GUITextBlock>().Font = subSelection.GetChild<GUITextBlock>().Font = modeSelection.GetChild<GUITextBlock>().Font = GUI.SmallFont;
|
||||
if (playStyleText != null)
|
||||
{
|
||||
playStyleText.Font = playStyleText.GetChild<GUITextBlock>().Font = GUI.SmallFont;
|
||||
}
|
||||
}
|
||||
|
||||
var allowSpectating = new GUITickBox(new RectTransform(new Vector2(1, elementHeight), content.RectTransform), TextManager.Get("ServerListAllowSpectating"))
|
||||
@@ -279,7 +290,6 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
else
|
||||
{
|
||||
List<string> availableWorkshopUrls = new List<string>();
|
||||
for (int i = 0; i < ContentPackageNames.Count; i++)
|
||||
{
|
||||
var packageText = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.15f), contentPackageList.Content.RectTransform) { MinSize = new Point(0, 15) },
|
||||
@@ -289,22 +299,15 @@ namespace Barotrauma.Networking
|
||||
};
|
||||
if (i < ContentPackageHashes.Count)
|
||||
{
|
||||
if (GameMain.Config.SelectedContentPackages.Any(cp => cp.MD5hash.Hash == ContentPackageHashes[i]))
|
||||
if (ContentPackage.AllPackages.Any(cp => cp.MD5hash.Hash == ContentPackageHashes[i]))
|
||||
{
|
||||
packageText.Selected = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
//matching content package found, but it hasn't been enabled
|
||||
if (ContentPackage.List.Any(cp => cp.MD5hash.Hash == ContentPackageHashes[i]))
|
||||
{
|
||||
packageText.TextColor = GUI.Style.Orange;
|
||||
packageText.ToolTip = TextManager.GetWithVariable("ServerListContentPackageNotEnabled", "[contentpackage]", ContentPackageNames[i]);
|
||||
}
|
||||
//workshop download link found
|
||||
else if (i < ContentPackageWorkshopUrls.Count && !string.IsNullOrEmpty(ContentPackageWorkshopUrls[i]))
|
||||
if (i < ContentPackageWorkshopIds.Count && ContentPackageWorkshopIds[i] != 0)
|
||||
{
|
||||
availableWorkshopUrls.Add(ContentPackageWorkshopUrls[i]);
|
||||
packageText.TextColor = Color.Yellow;
|
||||
packageText.ToolTip = TextManager.GetWithVariable("ServerListIncompatibleContentPackageWorkshopAvailable", "[contentpackage]", ContentPackageNames[i]);
|
||||
}
|
||||
@@ -316,21 +319,6 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
}
|
||||
if (availableWorkshopUrls.Count > 0)
|
||||
{
|
||||
var workshopBtn = new GUIButton(new RectTransform(new Vector2(1.0f, 0.1f), content.RectTransform), TextManager.Get("ServerListSubscribeMissingPackages"))
|
||||
{
|
||||
ToolTip = TextManager.Get(SteamManager.IsInitialized ? "ServerListSubscribeMissingPackagesTooltip" : "ServerListSubscribeMissingPackagesTooltipNoSteam"),
|
||||
Enabled = SteamManager.IsInitialized,
|
||||
OnClicked = (btn, userdata) =>
|
||||
{
|
||||
GameMain.SteamWorkshopScreen.SubscribeToPackages(availableWorkshopUrls);
|
||||
GameMain.SteamWorkshopScreen.Select();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
workshopBtn.TextBlock.AutoScaleHorizontal = true;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -391,7 +379,7 @@ namespace Barotrauma.Networking
|
||||
if (bool.TryParse(element.GetAttributeString("UsingWhiteList", ""), out bool whitelistTemp)) { info.UsingWhiteList = whitelistTemp; }
|
||||
if (Enum.TryParse(element.GetAttributeString("TraitorsEnabled", ""), out YesNoMaybe traitorsTemp)) { info.TraitorsEnabled = traitorsTemp; }
|
||||
if (Enum.TryParse(element.GetAttributeString("SubSelectionMode", ""), out SelectionMode subSelectionTemp)) { info.SubSelectionMode = subSelectionTemp; }
|
||||
if (Enum.TryParse(element.GetAttributeString("ModeSelectionMode", ""), out SelectionMode modeSelectionTemp)) { info.ModeSelectionMode = subSelectionTemp; }
|
||||
if (Enum.TryParse(element.GetAttributeString("ModeSelectionMode", ""), out SelectionMode modeSelectionTemp)) { info.ModeSelectionMode = modeSelectionTemp; }
|
||||
if (bool.TryParse(element.GetAttributeString("VoipEnabled", ""), out bool voipTemp)) { info.VoipEnabled = voipTemp; }
|
||||
if (bool.TryParse(element.GetAttributeString("KarmaEnabled", ""), out bool karmaTemp)) { info.KarmaEnabled = karmaTemp; }
|
||||
if (bool.TryParse(element.GetAttributeString("FriendlyFireEnabled", ""), out bool friendlyFireTemp)) { info.FriendlyFireEnabled = friendlyFireTemp; }
|
||||
|
||||
@@ -477,10 +477,6 @@ namespace Barotrauma.Networking
|
||||
GUITextBlock.AutoScaleAndNormalize(playStyleTickBoxes.Select(t => t.TextBlock));
|
||||
playstyleList.RectTransform.MinSize = new Point(0, (int)(playstyleList.Content.Children.First().Rect.Height * 2.0f + playstyleList.Padding.Y + playstyleList.Padding.W));
|
||||
|
||||
var endBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), roundsTab.RectTransform),
|
||||
TextManager.Get("ServerSettingsEndRoundWhenDestReached"));
|
||||
GetPropertyData("EndRoundAtLevelEnd").AssignGUIComponent(endBox);
|
||||
|
||||
var endVoteBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), roundsTab.RectTransform),
|
||||
TextManager.Get("ServerSettingsEndRoundVoting"));
|
||||
GetPropertyData("AllowEndVoting").AssignGUIComponent(endVoteBox);
|
||||
@@ -569,6 +565,8 @@ namespace Barotrauma.Networking
|
||||
};
|
||||
slider.OnMoved(slider, slider.BarScroll);
|
||||
|
||||
var traitorsMinPlayerCount = CreateLabeledNumberInput(roundsTab, "ServerSettingsTraitorsMinPlayerCount", 1, 16, "ServerSettingsTraitorsMinPlayerCountToolTip");
|
||||
GetPropertyData("TraitorsMinPlayerCount").AssignGUIComponent(traitorsMinPlayerCount);
|
||||
|
||||
var ragdollButtonBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), roundsTab.RectTransform), TextManager.Get("ServerSettingsAllowRagdollButton"));
|
||||
GetPropertyData("AllowRagdollButton").AssignGUIComponent(ragdollButtonBox);
|
||||
@@ -576,53 +574,6 @@ namespace Barotrauma.Networking
|
||||
var disableBotConversationsBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), roundsTab.RectTransform), TextManager.Get("ServerSettingsDisableBotConversations"));
|
||||
GetPropertyData("DisableBotConversations").AssignGUIComponent(disableBotConversationsBox);
|
||||
|
||||
/*var traitorRatioBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), roundsTab.RectTransform), TextManager.Get("ServerSettingsUseTraitorRatio"));
|
||||
|
||||
CreateLabeledSlider(roundsTab, "", out slider, out sliderLabel);
|
||||
var traitorRatioSlider = slider;
|
||||
traitorRatioBox.OnSelected = (GUITickBox) =>
|
||||
{
|
||||
traitorRatioSlider.OnMoved(traitorRatioSlider, traitorRatioSlider.BarScroll);
|
||||
return true;
|
||||
};
|
||||
|
||||
if (TraitorUseRatio)
|
||||
{
|
||||
traitorRatioSlider.Range = new Vector2(0.1f, 1.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
traitorRatioSlider.Range = new Vector2(1.0f, maxPlayers);
|
||||
}
|
||||
|
||||
string traitorRatioLabel = TextManager.Get("ServerSettingsTraitorRatio") + " ";
|
||||
string traitorCountLabel = TextManager.Get("ServerSettingsTraitorCount") + " ";
|
||||
|
||||
traitorRatioSlider.Range = new Vector2(0.1f, 1.0f);
|
||||
traitorRatioSlider.OnMoved = (GUIScrollBar scrollBar, float barScroll) =>
|
||||
{
|
||||
GUITextBlock traitorText = scrollBar.UserData as GUITextBlock;
|
||||
if (traitorRatioBox.Selected)
|
||||
{
|
||||
scrollBar.Step = 0.01f;
|
||||
scrollBar.Range = new Vector2(0.1f, 1.0f);
|
||||
traitorText.Text = traitorRatioLabel + (int)MathUtils.Round(scrollBar.BarScrollValue * 100.0f, 1.0f) + " %";
|
||||
}
|
||||
else
|
||||
{
|
||||
scrollBar.Step = 1f / (maxPlayers - 1);
|
||||
scrollBar.Range = new Vector2(1.0f, maxPlayers);
|
||||
traitorText.Text = traitorCountLabel + scrollBar.BarScrollValue;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
GetPropertyData("TraitorUseRatio").AssignGUIComponent(traitorRatioBox);
|
||||
GetPropertyData("TraitorRatio").AssignGUIComponent(traitorRatioSlider);
|
||||
|
||||
traitorRatioSlider.OnMoved(traitorRatioSlider, traitorRatioSlider.BarScroll);
|
||||
traitorRatioBox.OnSelected(traitorRatioBox);*/
|
||||
|
||||
var buttonHolder = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.07f), roundsTab.RectTransform), isHorizontal: true)
|
||||
{
|
||||
Stretch = true,
|
||||
@@ -919,7 +870,7 @@ namespace Barotrauma.Networking
|
||||
slider.UserData = label;
|
||||
}
|
||||
|
||||
private GUINumberInput CreateLabeledNumberInput(GUIComponent parent, string labelTag, int min, int max)
|
||||
private GUINumberInput CreateLabeledNumberInput(GUIComponent parent, string labelTag, int min, int max, string toolTipTag = null)
|
||||
{
|
||||
var container = new GUILayoutGroup(new RectTransform(new Vector2(1.0f, 0.1f), parent.RectTransform), isHorizontal: true)
|
||||
{
|
||||
@@ -928,11 +879,15 @@ namespace Barotrauma.Networking
|
||||
ToolTip = TextManager.Get(labelTag)
|
||||
};
|
||||
|
||||
new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), container.RectTransform),
|
||||
var label = new GUITextBlock(new RectTransform(new Vector2(0.7f, 1.0f), container.RectTransform),
|
||||
TextManager.Get(labelTag), textAlignment: Alignment.CenterLeft, font: GUI.SmallFont)
|
||||
{
|
||||
AutoScaleHorizontal = true
|
||||
};
|
||||
if (!string.IsNullOrEmpty(toolTipTag))
|
||||
{
|
||||
label.ToolTip = TextManager.Get(toolTipTag);
|
||||
}
|
||||
var input = new GUINumberInput(new RectTransform(new Vector2(0.3f, 1.0f), container.RectTransform), GUINumberInput.NumberType.Int)
|
||||
{
|
||||
MinValueInt = min,
|
||||
|
||||
@@ -1,22 +1,18 @@
|
||||
using Barotrauma.Networking;
|
||||
using Barotrauma.IO;
|
||||
using Barotrauma.Networking;
|
||||
using RestSharp;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Barotrauma.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using RestSharp.Contrib;
|
||||
using System.Xml.Linq;
|
||||
using Color = Microsoft.Xna.Framework.Color;
|
||||
using System.Runtime.InteropServices;
|
||||
using NLog.Fluent;
|
||||
|
||||
namespace Barotrauma.Steam
|
||||
{
|
||||
static partial class SteamManager
|
||||
{
|
||||
private static Dictionary<Steamworks.Data.PublishedFileId, Task> modCopiesInProgress = new Dictionary<Steamworks.Data.PublishedFileId, Task>();
|
||||
private static readonly Dictionary<Steamworks.Data.PublishedFileId, Task> modCopiesInProgress = new Dictionary<Steamworks.Data.PublishedFileId, Task>();
|
||||
|
||||
private static void InitializeProjectSpecific()
|
||||
{
|
||||
@@ -49,6 +45,9 @@ namespace Barotrauma.Steam
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
#if !DEBUG
|
||||
DebugConsole.ThrowError("SteamManager initialization threw an exception", e);
|
||||
#endif
|
||||
isInitialized = false;
|
||||
initializationErrors.Add("SteamClientInitFailed");
|
||||
}
|
||||
@@ -85,28 +84,6 @@ namespace Barotrauma.Steam
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void UpdateProjectSpecific(float deltaTime)
|
||||
{
|
||||
if (ugcSubscriptionTasks != null)
|
||||
{
|
||||
var ugcSubscriptionKeys = ugcSubscriptionTasks.Keys.ToList();
|
||||
foreach (var key in ugcSubscriptionKeys)
|
||||
{
|
||||
var task = ugcSubscriptionTasks[key];
|
||||
|
||||
if (task.IsCompleted)
|
||||
{
|
||||
if (!task.IsCompletedSuccessfully)
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to subscribe to a Steam Workshop item with id " + key.ToString() + ": TaskStatus = " + task.Status.ToString());
|
||||
}
|
||||
ugcSubscriptionTasks.Remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task InitRelayNetworkAccess()
|
||||
{
|
||||
if (!IsInitialized) { return; }
|
||||
@@ -209,13 +186,13 @@ namespace Barotrauma.Steam
|
||||
return;
|
||||
}
|
||||
|
||||
var contentPackages = GameMain.Config.SelectedContentPackages.Where(cp => cp.HasMultiplayerIncompatibleContent);
|
||||
var contentPackages = GameMain.Config.AllEnabledPackages.Where(cp => cp.HasMultiplayerIncompatibleContent);
|
||||
|
||||
currentLobby?.SetData("name", serverSettings.ServerName);
|
||||
currentLobby?.SetData("playercount", (GameMain.Client?.ConnectedClients?.Count ?? 0).ToString());
|
||||
currentLobby?.SetData("maxplayernum", serverSettings.MaxPlayers.ToString());
|
||||
//currentLobby?.SetData("hostipaddress", lobbyIP);
|
||||
string pingLocation = Steamworks.SteamNetworkingUtils.LocalPingLocation.ToString();
|
||||
string pingLocation = Steamworks.SteamNetworkingUtils.LocalPingLocation?.ToString();
|
||||
currentLobby?.SetData("pinglocation", pingLocation ?? "");
|
||||
currentLobby?.SetData("lobbyowner", SteamIDUInt64ToString(GetSteamID()));
|
||||
currentLobby?.SetData("haspassword", serverSettings.HasPassword.ToString());
|
||||
@@ -225,7 +202,7 @@ namespace Barotrauma.Steam
|
||||
|
||||
currentLobby?.SetData("contentpackage", string.Join(",", contentPackages.Select(cp => cp.Name)));
|
||||
currentLobby?.SetData("contentpackagehash", string.Join(",", contentPackages.Select(cp => cp.MD5hash.Hash)));
|
||||
currentLobby?.SetData("contentpackageurl", string.Join(",", contentPackages.Select(cp => cp.SteamWorkshopUrl ?? "")));
|
||||
currentLobby?.SetData("contentpackageid", string.Join(",", contentPackages.Select(cp => cp.SteamWorkshopId)));
|
||||
currentLobby?.SetData("usingwhitelist", (serverSettings.Whitelist != null && serverSettings.Whitelist.Enabled).ToString());
|
||||
currentLobby?.SetData("modeselectionmode", serverSettings.ModeSelectionMode.ToString());
|
||||
currentLobby?.SetData("subselectionmode", serverSettings.SubSelectionMode.ToString());
|
||||
@@ -280,9 +257,8 @@ namespace Barotrauma.Steam
|
||||
{
|
||||
if (!isInitialized) { return false; }
|
||||
|
||||
|
||||
int doneTasks = 0;
|
||||
Action taskDone = () =>
|
||||
void taskDone()
|
||||
{
|
||||
doneTasks++;
|
||||
if (doneTasks >= 2)
|
||||
@@ -290,52 +266,64 @@ namespace Barotrauma.Steam
|
||||
serverQueryFinished?.Invoke();
|
||||
serverQueryFinished = null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
//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);
|
||||
|
||||
Steamworks.Dispatch.OnDebugCallback = (callbackType, contents, isServer) =>
|
||||
{
|
||||
DebugConsole.NewMessage($"{callbackType}: " + contents, Color.Yellow);
|
||||
};
|
||||
TaskPool.Add("LobbyQueryRequest", lobbyQuery.RequestAsync(),
|
||||
(t) =>
|
||||
{
|
||||
var lobbies = ((Task<Steamworks.Data.Lobby[]>)t).Result;
|
||||
foreach (var lobby in lobbies)
|
||||
{
|
||||
if (string.IsNullOrEmpty(lobby.GetData("name"))) { continue; }
|
||||
|
||||
ServerInfo serverInfo = new ServerInfo();
|
||||
serverInfo.ServerName = lobby.GetData("name");
|
||||
serverInfo.OwnerID = SteamIDStringToUInt64(lobby.GetData("lobbyowner"));
|
||||
serverInfo.LobbyID = lobby.Id;
|
||||
bool.TryParse(lobby.GetData("haspassword"), out serverInfo.HasPassword);
|
||||
serverInfo.PlayerCount = int.TryParse(lobby.GetData("playercount"), out int playerCount) ? playerCount : 0;
|
||||
serverInfo.MaxPlayers = int.TryParse(lobby.GetData("maxplayernum"), out int maxPlayers) ? maxPlayers : 1;
|
||||
serverInfo.RespondedToSteamQuery = true;
|
||||
|
||||
AssignLobbyDataToServerInfo(lobby, serverInfo);
|
||||
|
||||
addToServerList(serverInfo);
|
||||
}
|
||||
taskDone();
|
||||
Steamworks.Dispatch.OnDebugCallback = null;
|
||||
if (t.Status == TaskStatus.Faulted)
|
||||
{
|
||||
TaskPool.PrintTaskExceptions(t, "Failed to retrieve SteamP2P lobbies");
|
||||
taskDone();
|
||||
return;
|
||||
}
|
||||
var lobbies = ((Task<Steamworks.Data.Lobby[]>)t).Result;
|
||||
if (lobbies != null)
|
||||
{
|
||||
foreach (var lobby in lobbies)
|
||||
{
|
||||
if (string.IsNullOrEmpty(lobby.GetData("name"))) { continue; }
|
||||
|
||||
ServerInfo serverInfo = new ServerInfo();
|
||||
serverInfo.ServerName = lobby.GetData("name");
|
||||
serverInfo.OwnerID = SteamIDStringToUInt64(lobby.GetData("lobbyowner"));
|
||||
serverInfo.LobbyID = lobby.Id;
|
||||
bool.TryParse(lobby.GetData("haspassword"), out serverInfo.HasPassword);
|
||||
serverInfo.PlayerCount = int.TryParse(lobby.GetData("playercount"), out int playerCount) ? playerCount : 0;
|
||||
serverInfo.MaxPlayers = int.TryParse(lobby.GetData("maxplayernum"), out int maxPlayers) ? maxPlayers : 1;
|
||||
serverInfo.RespondedToSteamQuery = true;
|
||||
|
||||
AssignLobbyDataToServerInfo(lobby, serverInfo);
|
||||
|
||||
addToServerList(serverInfo);
|
||||
}
|
||||
}
|
||||
taskDone();
|
||||
});
|
||||
|
||||
Steamworks.ServerList.Internet serverQuery = new Steamworks.ServerList.Internet();
|
||||
Action<Steamworks.Data.ServerInfo, bool> onServer = (Steamworks.Data.ServerInfo info, bool responsive) =>
|
||||
void onServer(Steamworks.Data.ServerInfo info, bool responsive)
|
||||
{
|
||||
if (string.IsNullOrEmpty(info.Name)) { return; }
|
||||
|
||||
ServerInfo serverInfo = new ServerInfo();
|
||||
serverInfo.ServerName = info.Name;
|
||||
serverInfo.IP = info.Address.ToString();
|
||||
serverInfo.Port = info.ConnectionPort.ToString();
|
||||
serverInfo.PlayerCount = info.Players;
|
||||
serverInfo.MaxPlayers = info.MaxPlayers;
|
||||
serverInfo.RespondedToSteamQuery = responsive;
|
||||
ServerInfo serverInfo = new ServerInfo
|
||||
{
|
||||
ServerName = info.Name,
|
||||
HasPassword = info.Passworded,
|
||||
IP = info.Address.ToString(),
|
||||
Port = info.ConnectionPort.ToString(),
|
||||
PlayerCount = info.Players,
|
||||
MaxPlayers = info.MaxPlayers,
|
||||
RespondedToSteamQuery = responsive
|
||||
};
|
||||
|
||||
if (responsive)
|
||||
{
|
||||
@@ -344,11 +332,11 @@ namespace Barotrauma.Steam
|
||||
{
|
||||
if (t.Status == TaskStatus.Faulted)
|
||||
{
|
||||
TaskPool.PrintTaskExceptions(t, "Failed to retrieve rules for "+info.Name);
|
||||
TaskPool.PrintTaskExceptions(t, "Failed to retrieve rules for " + info.Name);
|
||||
return;
|
||||
}
|
||||
|
||||
var rules = ((Task<Dictionary<string,string>>)t).Result;
|
||||
var rules = ((Task<Dictionary<string, string>>)t).Result;
|
||||
AssignServerRulesToServerInfo(rules, serverInfo);
|
||||
|
||||
CrossThread.RequestExecutionOnMainThread(() =>
|
||||
@@ -365,7 +353,7 @@ namespace Barotrauma.Steam
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
serverQuery.OnResponsiveServer += (info) => onServer(info, true);
|
||||
serverQuery.OnUnresponsiveServer += (info) => onServer(info, false);
|
||||
|
||||
@@ -393,11 +381,20 @@ namespace Barotrauma.Steam
|
||||
|
||||
serverInfo.ContentPackageNames.AddRange(lobby.GetData("contentpackage").Split(','));
|
||||
serverInfo.ContentPackageHashes.AddRange(lobby.GetData("contentpackagehash").Split(','));
|
||||
serverInfo.ContentPackageWorkshopUrls.AddRange(lobby.GetData("contentpackageurl").Split(','));
|
||||
|
||||
string workshopIdData = lobby.GetData("contentpackageid");
|
||||
if (!string.IsNullOrEmpty(workshopIdData))
|
||||
{
|
||||
serverInfo.ContentPackageWorkshopIds.AddRange(ParseWorkshopIds(workshopIdData));
|
||||
}
|
||||
else
|
||||
{
|
||||
string[] workshopUrls = lobby.GetData("contentpackageurl").Split(',');
|
||||
serverInfo.ContentPackageWorkshopIds.AddRange(WorkshopUrlsToIds(workshopUrls));
|
||||
}
|
||||
|
||||
serverInfo.UsingWhiteList = getLobbyBool("usingwhitelist");
|
||||
SelectionMode selectionMode;
|
||||
if (Enum.TryParse(lobby.GetData("modeselectionmode"), out selectionMode)) { serverInfo.ModeSelectionMode = selectionMode; }
|
||||
if (Enum.TryParse(lobby.GetData("modeselectionmode"), out SelectionMode selectionMode)) { serverInfo.ModeSelectionMode = selectionMode; }
|
||||
if (Enum.TryParse(lobby.GetData("subselectionmode"), out selectionMode)) { serverInfo.SubSelectionMode = selectionMode; }
|
||||
|
||||
serverInfo.AllowSpectating = getLobbyBool("allowspectating");
|
||||
@@ -412,11 +409,12 @@ namespace Barotrauma.Steam
|
||||
if (Enum.TryParse(lobby.GetData("playstyle"), out PlayStyle playStyle)) serverInfo.PlayStyle = playStyle;
|
||||
|
||||
if (serverInfo.ContentPackageNames.Count != serverInfo.ContentPackageHashes.Count ||
|
||||
serverInfo.ContentPackageHashes.Count != serverInfo.ContentPackageWorkshopUrls.Count)
|
||||
serverInfo.ContentPackageHashes.Count != serverInfo.ContentPackageWorkshopIds.Count)
|
||||
{
|
||||
//invalid contentpackage info
|
||||
serverInfo.ContentPackageNames.Clear();
|
||||
serverInfo.ContentPackageHashes.Clear();
|
||||
serverInfo.ContentPackageWorkshopIds.Clear();
|
||||
}
|
||||
|
||||
string pingLocation = lobby.GetData("pinglocation");
|
||||
@@ -449,10 +447,18 @@ namespace Barotrauma.Steam
|
||||
|
||||
serverInfo.ContentPackageNames.Clear();
|
||||
serverInfo.ContentPackageHashes.Clear();
|
||||
serverInfo.ContentPackageWorkshopUrls.Clear();
|
||||
serverInfo.ContentPackageWorkshopIds.Clear();
|
||||
if (rules.ContainsKey("contentpackage")) serverInfo.ContentPackageNames.AddRange(rules["contentpackage"].Split(','));
|
||||
if (rules.ContainsKey("contentpackagehash")) serverInfo.ContentPackageHashes.AddRange(rules["contentpackagehash"].Split(','));
|
||||
if (rules.ContainsKey("contentpackageurl")) serverInfo.ContentPackageWorkshopUrls.AddRange(rules["contentpackageurl"].Split(','));
|
||||
if (rules.ContainsKey("contentpackageid"))
|
||||
{
|
||||
serverInfo.ContentPackageWorkshopIds.AddRange(ParseWorkshopIds(rules["contentpackageid"]));
|
||||
}
|
||||
else if (rules.ContainsKey("contentpackageurl"))
|
||||
{
|
||||
string[] workshopUrls = rules["contentpackageurl"].Split(',');
|
||||
serverInfo.ContentPackageWorkshopIds.AddRange(WorkshopUrlsToIds(workshopUrls));
|
||||
}
|
||||
|
||||
if (rules.ContainsKey("usingwhitelist")) serverInfo.UsingWhiteList = rules["usingwhitelist"] == "True";
|
||||
if (rules.ContainsKey("modeselectionmode"))
|
||||
@@ -479,37 +485,16 @@ namespace Barotrauma.Steam
|
||||
}
|
||||
|
||||
if (serverInfo.ContentPackageNames.Count != serverInfo.ContentPackageHashes.Count ||
|
||||
serverInfo.ContentPackageHashes.Count != serverInfo.ContentPackageWorkshopUrls.Count)
|
||||
serverInfo.ContentPackageHashes.Count != serverInfo.ContentPackageWorkshopIds.Count)
|
||||
{
|
||||
//invalid contentpackage info
|
||||
serverInfo.ContentPackageNames.Clear();
|
||||
serverInfo.ContentPackageHashes.Clear();
|
||||
serverInfo.ContentPackageWorkshopIds.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public static ulong GetWorkshopItemIDFromUrl(string url)
|
||||
{
|
||||
try
|
||||
{
|
||||
Uri uri = new Uri(url);
|
||||
string idStr = HttpUtility.ParseQueryString(uri.Query).Get("id");
|
||||
if (ulong.TryParse(idStr, out ulong id))
|
||||
{
|
||||
return id;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to get Workshop item ID from the url \"" + url + "\"!", e);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#region Connecting to servers
|
||||
|
||||
//TODO: reimplement server list queries
|
||||
|
||||
#region Connecting to servers
|
||||
private static Steamworks.AuthTicket currentTicket = null;
|
||||
public static Steamworks.AuthTicket GetAuthSessionTicket()
|
||||
{
|
||||
@@ -545,9 +530,9 @@ namespace Barotrauma.Steam
|
||||
Steamworks.SteamUser.EndAuthSession(clientSteamID);
|
||||
}
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Workshop
|
||||
#region Workshop
|
||||
|
||||
public const string WorkshopItemPreviewImageFolder = "Workshop";
|
||||
public const string PreviewImageName = "PreviewImage.png";
|
||||
@@ -620,7 +605,8 @@ namespace Barotrauma.Steam
|
||||
.WithLongDescription();
|
||||
if (requireTags != null) query.WithTags(requireTags);
|
||||
|
||||
TaskPool.Add("GetPopularWorkshopItems", GetWorkshopItemsAsync(query, amount, (item) => !item.IsSubscribed), (task) => {
|
||||
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
|
||||
@@ -669,47 +655,82 @@ namespace Barotrauma.Steam
|
||||
TaskPool.Add("GetPublishedWorkshopItems", GetWorkshopItemsAsync(query), (task) => { onItemsFound?.Invoke(((Task<List<Steamworks.Ugc.Item>>)task).Result); });
|
||||
}
|
||||
|
||||
private static Dictionary<ulong, Task> ugcSubscriptionTasks;
|
||||
private static readonly HashSet<ulong> pendingWorkshopSubscriptions = new HashSet<ulong>();
|
||||
|
||||
public static void SubscribeToWorkshopItem(string itemUrl)
|
||||
{
|
||||
if (!isInitialized) return;
|
||||
|
||||
ulong id = GetWorkshopItemIDFromUrl(itemUrl);
|
||||
|
||||
SubscribeToWorkshopItem(id);
|
||||
}
|
||||
|
||||
public static void SubscribeToWorkshopItem(ulong id)
|
||||
public static void SubscribeToWorkshopItem(ulong id, Action onInstalled = null)
|
||||
{
|
||||
if (!isInitialized) return;
|
||||
|
||||
if (id == 0) { return; }
|
||||
|
||||
if (ugcSubscriptionTasks?.ContainsKey(id) ?? false) { return; }
|
||||
if (pendingWorkshopSubscriptions.Contains(id)) { return; }
|
||||
|
||||
ugcSubscriptionTasks ??= new Dictionary<ulong, Task>();
|
||||
ugcSubscriptionTasks.Add(id, Task.Run(async () =>
|
||||
{
|
||||
Steamworks.Ugc.Item? item = await Steamworks.SteamUGC.QueryFileAsync(id);
|
||||
pendingWorkshopSubscriptions.Add(id);
|
||||
TaskPool.Add(
|
||||
$"SubscribeToWorkshopItem({id})",
|
||||
Task.Run(async () =>
|
||||
{
|
||||
Steamworks.Ugc.Item? item = await Steamworks.SteamUGC.QueryFileAsync(id);
|
||||
|
||||
if (!item.HasValue)
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to find a Steam Workshop item with the ID " + id.ToString() + ".");
|
||||
return;
|
||||
}
|
||||
if (!item.HasValue)
|
||||
{
|
||||
DebugConsole.ThrowError($"Failed to find a Steam Workshop item with the ID {id}.");
|
||||
return null;
|
||||
}
|
||||
|
||||
bool subscribed = await item?.Subscribe();
|
||||
if (!subscribed)
|
||||
if (!(item?.IsSubscribed ?? false))
|
||||
{
|
||||
bool subscribed = await item?.Subscribe();
|
||||
if (!subscribed)
|
||||
{
|
||||
DebugConsole.ThrowError($"Failed to subscribe to Steam Workshop item with the ID {id}.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return item;
|
||||
}),
|
||||
(t) =>
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to subscribe to Steam Workshop item with the ID " + id.ToString() + ".");
|
||||
}
|
||||
bool downloading = item?.Download() ?? false;
|
||||
if (!downloading)
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to start downloading Steam Workshop item with the ID " + id.ToString() + ".");
|
||||
}
|
||||
}));
|
||||
bool shouldCleanup = true;
|
||||
if (t.IsFaulted)
|
||||
{
|
||||
TaskPool.PrintTaskExceptions(t, $"Workshop subscription task {id} faulted");
|
||||
}
|
||||
else
|
||||
{
|
||||
var item = ((Task<Steamworks.Ugc.Item?>)t).Result;
|
||||
if (item != null)
|
||||
{
|
||||
if (item?.IsInstalled ?? false)
|
||||
{
|
||||
onInstalled?.Invoke();
|
||||
}
|
||||
else
|
||||
{
|
||||
void _onInstalled()
|
||||
{
|
||||
onInstalled?.Invoke();
|
||||
pendingWorkshopSubscriptions.Remove(id);
|
||||
}
|
||||
bool downloading = item?.Download(_onInstalled) ?? false;
|
||||
if (!downloading)
|
||||
{
|
||||
DebugConsole.ThrowError($"Failed to start downloading Steam Workshop item with the ID {id}.");
|
||||
}
|
||||
else
|
||||
{
|
||||
shouldCleanup = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldCleanup)
|
||||
{
|
||||
pendingWorkshopSubscriptions.Remove(id);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void CreateWorkshopItemStaging(ContentPackage contentPackage, out Steamworks.Ugc.Editor? itemEditor)
|
||||
@@ -790,9 +811,9 @@ namespace Barotrauma.Steam
|
||||
itemEditor = itemEditor?.WithPrivateVisibility();
|
||||
}
|
||||
|
||||
if (!CheckWorkshopItemEnabled(existingItem))
|
||||
if (!CheckWorkshopItemInstalled(existingItem))
|
||||
{
|
||||
if (!EnableWorkShopItem(existingItem, out string errorMsg))
|
||||
if (!InstallWorkshopItem(existingItem, out string errorMsg))
|
||||
{
|
||||
DebugConsole.NewMessage(errorMsg, Color.Red);
|
||||
new GUIMessageBox(
|
||||
@@ -804,9 +825,9 @@ namespace Barotrauma.Steam
|
||||
}
|
||||
}
|
||||
|
||||
ContentPackage tempContentPackage = new ContentPackage(Path.Combine(existingItem?.Directory, MetadataFileName)) { SteamWorkshopUrl = existingItem.Value.Url };
|
||||
ContentPackage tempContentPackage = new ContentPackage(Path.Combine(existingItem?.Directory, MetadataFileName)) { SteamWorkshopId = existingItem.Value.Id };
|
||||
string installedContentPackagePath = Path.GetFullPath(GetWorkshopItemContentPackagePath(tempContentPackage));
|
||||
contentPackage = ContentPackage.List.Find(cp => Path.GetFullPath(cp.Path) == installedContentPackagePath);
|
||||
contentPackage = ContentPackage.AllPackages.FirstOrDefault(cp => Path.GetFullPath(cp.Path) == installedContentPackagePath);
|
||||
|
||||
itemEditor = itemEditor?.WithContent(Path.GetDirectoryName(installedContentPackagePath));
|
||||
|
||||
@@ -923,7 +944,7 @@ namespace Barotrauma.Steam
|
||||
workshopPublishStatus.Result = task.Result;
|
||||
DebugConsole.NewMessage("Published workshop item " + item?.Title + " successfully.", Microsoft.Xna.Framework.Color.LightGreen);
|
||||
|
||||
contentPackage.SteamWorkshopUrl = $"http://steamcommunity.com/sharedfiles/filedetails/?source=Facepunch.Steamworks&id={task.Result.FileId.Value}";
|
||||
contentPackage.SteamWorkshopId = task.Result.FileId.Value;
|
||||
//NOTE: This sets InstallTime one hour into the future to guarantee
|
||||
//that the published content package won't be autoupdated incorrectly.
|
||||
//Change if it causes issues.
|
||||
@@ -937,9 +958,9 @@ namespace Barotrauma.Steam
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enables a workshop item by moving it to the game folder.
|
||||
/// Installs a workshop item by moving it to the game folder.
|
||||
/// </summary>
|
||||
public static bool EnableWorkShopItem(Steamworks.Ugc.Item? item, out string errorMsg, bool selectContentPackage = false, bool suppressInstallNotif = false)
|
||||
public static bool InstallWorkshopItem(Steamworks.Ugc.Item? item, out string errorMsg, bool enableContentPackage = false, bool suppressInstallNotif = false)
|
||||
{
|
||||
if (!(item?.IsInstalled ?? false))
|
||||
{
|
||||
@@ -959,11 +980,11 @@ namespace Barotrauma.Steam
|
||||
|
||||
ContentPackage contentPackage = new ContentPackage(metaDataFilePath)
|
||||
{
|
||||
SteamWorkshopUrl = item?.Url
|
||||
SteamWorkshopId = item?.Id ?? 0
|
||||
};
|
||||
string newContentPackagePath = GetWorkshopItemContentPackagePath(contentPackage);
|
||||
|
||||
List<ContentPackage> existingPackages = ContentPackage.List.Where(cp => cp.Path.CleanUpPath() == newContentPackagePath.CleanUpPath()).ToList();
|
||||
List<ContentPackage> existingPackages = ContentPackage.AllPackages.Where(cp => cp.Path.CleanUpPath() == newContentPackagePath.CleanUpPath()).ToList();
|
||||
if (existingPackages.Any())
|
||||
{
|
||||
if (item?.Owner.Id != Steamworks.SteamClient.SteamId)
|
||||
@@ -975,7 +996,7 @@ namespace Barotrauma.Steam
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveMods(cp => !string.IsNullOrWhiteSpace(cp.SteamWorkshopUrl) && cp.SteamWorkshopUrl == contentPackage.SteamWorkshopUrl,
|
||||
RemoveMods(cp => cp.SteamWorkshopId != 0 && cp.SteamWorkshopId == contentPackage.SteamWorkshopId,
|
||||
false);
|
||||
}
|
||||
}
|
||||
@@ -1024,7 +1045,7 @@ namespace Barotrauma.Steam
|
||||
|
||||
var newPackage = new ContentPackage(cp.Path, newContentPackagePath)
|
||||
{
|
||||
SteamWorkshopUrl = item?.Url,
|
||||
SteamWorkshopId = item?.Id ?? 0,
|
||||
InstallTime = item?.Updated > item?.Created ? item?.Updated : item?.Created
|
||||
};
|
||||
|
||||
@@ -1045,17 +1066,17 @@ namespace Barotrauma.Steam
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(newContentPackagePath));
|
||||
}
|
||||
newPackage.Save(newContentPackagePath);
|
||||
ContentPackage.List.Add(newPackage);
|
||||
ContentPackage.AddPackage(newPackage);
|
||||
|
||||
if (selectContentPackage)
|
||||
if (enableContentPackage)
|
||||
{
|
||||
if (newPackage.CorePackage)
|
||||
if (newPackage.IsCorePackage)
|
||||
{
|
||||
GameMain.Config.SelectCorePackage(newPackage);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMain.Config.SelectContentPackage(newPackage);
|
||||
GameMain.Config.EnableRegularPackage(newPackage);
|
||||
}
|
||||
GameMain.Config.SaveNewPlayerConfig();
|
||||
|
||||
@@ -1213,40 +1234,21 @@ namespace Barotrauma.Steam
|
||||
return "";
|
||||
}
|
||||
|
||||
private static bool CheckFileEquality(string filePath1, string filePath2)
|
||||
{
|
||||
if (filePath1 == filePath2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
using (FileStream fs1 = File.OpenRead(filePath1))
|
||||
using (FileStream fs2 = File.OpenRead(filePath2))
|
||||
{
|
||||
Md5Hash hash1 = new Md5Hash(fs1);
|
||||
Md5Hash hash2 = new Md5Hash(fs2);
|
||||
return hash1.Hash == hash2.Hash;
|
||||
}
|
||||
}
|
||||
|
||||
private static void RemoveMods(Func<ContentPackage, bool> predicate, bool delete = true)
|
||||
{
|
||||
var toRemove = ContentPackage.List.Where(predicate).ToList();
|
||||
var packagesToDeselect = GameMain.Config.SelectedContentPackages.Where(p => toRemove.Contains(p)).ToList();
|
||||
var toRemoveCore = ContentPackage.CorePackages.Where(predicate).ToList();
|
||||
if (toRemoveCore.Contains(GameMain.Config.CurrentCorePackage)) { GameMain.Config.AutoSelectCorePackage(toRemoveCore); }
|
||||
|
||||
var toRemoveRegular = ContentPackage.RegularPackages.Where(predicate).ToList();
|
||||
var packagesToDeselect = GameMain.Config.EnabledRegularPackages.Where(p => toRemoveRegular.Contains(p)).ToList();
|
||||
foreach (var cp in packagesToDeselect)
|
||||
{
|
||||
if (cp.CorePackage)
|
||||
{
|
||||
GameMain.Config.AutoSelectCorePackage(toRemove);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMain.Config.DeselectContentPackage(cp);
|
||||
}
|
||||
GameMain.Config.DisableRegularPackage(cp);
|
||||
}
|
||||
|
||||
if (delete)
|
||||
{
|
||||
var toRemove = toRemoveCore.Concat(toRemoveRegular);
|
||||
foreach (var cp in toRemove)
|
||||
{
|
||||
try
|
||||
@@ -1258,22 +1260,19 @@ namespace Barotrauma.Steam
|
||||
{
|
||||
DebugConsole.ThrowError($"An error occurred while attempting to delete {Path.GetDirectoryName(cp.Path)}", e);
|
||||
}
|
||||
ContentPackage.RemovePackage(cp);
|
||||
}
|
||||
}
|
||||
|
||||
ContentPackage.List.RemoveAll(cp => toRemove.Contains(cp));
|
||||
GameMain.Config.SelectedContentPackages.RemoveAll(cp => !ContentPackage.List.Contains(cp));
|
||||
|
||||
ContentPackage.SortContentPackages();
|
||||
GameMain.Config.SaveNewPlayerConfig();
|
||||
|
||||
GameMain.Config.WarnIfContentPackageSelectionDirty();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disables a workshop item by removing the files from the game folder.
|
||||
/// Uninstalls a workshop item by removing the files from the game folder.
|
||||
/// </summary>
|
||||
public static bool DisableWorkShopItem(Steamworks.Ugc.Item? item, bool noLog, out string errorMsg)
|
||||
public static bool UninstallWorkshopItem(Steamworks.Ugc.Item? item, bool noLog, out string errorMsg)
|
||||
{
|
||||
errorMsg = null;
|
||||
if (!(item?.IsInstalled ?? false))
|
||||
@@ -1288,13 +1287,13 @@ namespace Barotrauma.Steam
|
||||
|
||||
ContentPackage contentPackage = new ContentPackage(Path.Combine(item?.Directory, MetadataFileName))
|
||||
{
|
||||
SteamWorkshopUrl = item?.Url
|
||||
SteamWorkshopId = item?.Id ?? 0
|
||||
};
|
||||
|
||||
GameMain.Config.SuppressModFolderWatcher = true;
|
||||
try
|
||||
{
|
||||
RemoveMods(cp => !string.IsNullOrWhiteSpace(cp.SteamWorkshopUrl) && cp.SteamWorkshopUrl == contentPackage.SteamWorkshopUrl);
|
||||
RemoveMods(cp => cp.SteamWorkshopId != 0 && cp.SteamWorkshopId == contentPackage.SteamWorkshopId);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -1330,7 +1329,7 @@ namespace Barotrauma.Steam
|
||||
return contentPackage.IsCompatible();
|
||||
}
|
||||
|
||||
public static bool CheckWorkshopItemEnabled(Steamworks.Ugc.Item? item)
|
||||
public static bool CheckWorkshopItemInstalled(Steamworks.Ugc.Item? item)
|
||||
{
|
||||
if (!(item?.IsInstalled ?? false)) { return false; }
|
||||
|
||||
@@ -1359,7 +1358,7 @@ namespace Barotrauma.Steam
|
||||
string errorMessage = "Metadata file for the Workshop item \"" + item?.Title +
|
||||
"\" not found. Could not combine path (" + (item?.Directory ?? "directory name empty") + ").";
|
||||
DebugConsole.ThrowError(errorMessage);
|
||||
GameAnalyticsManager.AddErrorEventOnce("SteamManager.CheckWorkshopItemEnabled:PathCombineException" + item?.Title,
|
||||
GameAnalyticsManager.AddErrorEventOnce("SteamManager.CheckWorkshopItemInstalled:PathCombineException" + item?.Title,
|
||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
errorMessage);
|
||||
return false;
|
||||
@@ -1373,12 +1372,12 @@ namespace Barotrauma.Steam
|
||||
|
||||
ContentPackage contentPackage = new ContentPackage(metaDataPath)
|
||||
{
|
||||
SteamWorkshopUrl = item?.Url
|
||||
SteamWorkshopId = item?.Id ?? 0
|
||||
};
|
||||
//make sure the contentpackage file is present
|
||||
if (!File.Exists(GetWorkshopItemContentPackagePath(contentPackage)) ||
|
||||
!ContentPackage.List.Any(cp => cp.SteamWorkshopUrl == contentPackage.SteamWorkshopUrl ||
|
||||
(string.IsNullOrWhiteSpace(cp.SteamWorkshopUrl) && cp.Name == contentPackage.Name)))
|
||||
!ContentPackage.AllPackages.Any(cp => cp.SteamWorkshopId == contentPackage.SteamWorkshopId ||
|
||||
(cp.SteamWorkshopId == 0 && cp.Name == contentPackage.Name)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -1399,9 +1398,9 @@ namespace Barotrauma.Steam
|
||||
|
||||
ContentPackage steamPackage = new ContentPackage(metaDataPath)
|
||||
{
|
||||
SteamWorkshopUrl = item?.Url
|
||||
SteamWorkshopId = item?.Id ?? 0
|
||||
};
|
||||
ContentPackage myPackage = ContentPackage.List.Find(cp => cp.SteamWorkshopUrl == steamPackage.SteamWorkshopUrl);
|
||||
ContentPackage myPackage = ContentPackage.AllPackages.FirstOrDefault(cp => cp.SteamWorkshopId == steamPackage.SteamWorkshopId);
|
||||
|
||||
if (myPackage?.InstallTime == null)
|
||||
{
|
||||
@@ -1427,7 +1426,7 @@ namespace Barotrauma.Steam
|
||||
GameMain.Config.SuppressModFolderWatcher = true;
|
||||
|
||||
//remove mods that the player is no longer subscribed to
|
||||
RemoveMods(cp => !string.IsNullOrWhiteSpace(cp.SteamWorkshopUrl) && !items.Any(it => it.Id == GetWorkshopItemIDFromUrl(cp.SteamWorkshopUrl)));
|
||||
RemoveMods(cp => cp.SteamWorkshopId != 0 && !items.Any(it => it.Id == cp.SteamWorkshopId));
|
||||
|
||||
GameMain.Config.SuppressModFolderWatcher = false;
|
||||
|
||||
@@ -1441,9 +1440,9 @@ namespace Barotrauma.Steam
|
||||
|
||||
bool installedSuccessfully = false;
|
||||
string errorMsg;
|
||||
if (!CheckWorkshopItemEnabled(item))
|
||||
if (!CheckWorkshopItemInstalled(item))
|
||||
{
|
||||
installedSuccessfully = EnableWorkShopItem(item, out errorMsg);
|
||||
installedSuccessfully = InstallWorkshopItem(item, out errorMsg);
|
||||
}
|
||||
else if (!CheckWorkshopItemUpToDate(item))
|
||||
{
|
||||
@@ -1529,12 +1528,12 @@ namespace Barotrauma.Steam
|
||||
{
|
||||
errorMsg = "";
|
||||
if (!(item?.IsInstalled ?? false)) { return false; }
|
||||
bool reenable = GameMain.Config.SelectedContentPackages.Any(p => !string.IsNullOrEmpty(p.SteamWorkshopUrl) && GetWorkshopItemIDFromUrl(p.SteamWorkshopUrl) == item?.Id);
|
||||
bool reenable = GameMain.Config.AllEnabledPackages.Any(p => p.SteamWorkshopId != 0 && p.SteamWorkshopId == item?.Id);
|
||||
if (item?.Owner.Id != Steamworks.SteamClient.SteamId)
|
||||
{
|
||||
if (!DisableWorkShopItem(item, false, out errorMsg)) { return false; }
|
||||
if (!UninstallWorkshopItem(item, false, out errorMsg)) { return false; }
|
||||
}
|
||||
if (!EnableWorkShopItem(item, errorMsg: out errorMsg, selectContentPackage: reenable)) { return false; }
|
||||
if (!InstallWorkshopItem(item, errorMsg: out errorMsg, enableContentPackage: reenable)) { return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1543,7 +1542,7 @@ namespace Barotrauma.Steam
|
||||
string packageName = contentPackage.Name.Trim();
|
||||
packageName = ToolBox.RemoveInvalidFileNameChars(packageName);
|
||||
while (packageName.Last() == '.') { packageName = packageName.Substring(0, packageName.Length-1); }
|
||||
//packageName = packageName + "_" + GetWorkshopItemIDFromUrl(contentPackage.SteamWorkshopUrl);
|
||||
//packageName = packageName + "_" + contentPackage.SteamWorkshopId.ToString();
|
||||
|
||||
return Path.Combine("Mods", packageName, MetadataFileName);
|
||||
}
|
||||
@@ -1559,8 +1558,7 @@ namespace Barotrauma.Steam
|
||||
attr.Name.ToString() == "characterfile") &&
|
||||
attr.Value.CleanUpPath().Contains("/"))
|
||||
{
|
||||
ContentType type = ContentType.None;
|
||||
Enum.TryParse(attr.Name.LocalName, true, out type);
|
||||
Enum.TryParse(attr.Name.LocalName, true, out ContentType type);
|
||||
attr.Value = CorrectContentFilePath(attr.Value, type, package, true);
|
||||
}
|
||||
}
|
||||
@@ -1615,8 +1613,7 @@ namespace Barotrauma.Steam
|
||||
if (checkIfFileExists)
|
||||
{
|
||||
bool exists = File.Exists(contentFilePath);
|
||||
if (type == ContentType.Executable ||
|
||||
type == ContentType.ServerExecutable)
|
||||
if (type == ContentType.ServerExecutable)
|
||||
{
|
||||
exists |= File.Exists(Path.GetFileNameWithoutExtension(contentFilePath) + ".dll");
|
||||
}
|
||||
@@ -1634,7 +1631,7 @@ namespace Barotrauma.Steam
|
||||
{
|
||||
if (checkIfFileExists)
|
||||
{
|
||||
ContentPackage otherContentPackage = ContentPackage.List.Find(cp => cp.Name.Equals(splitPath[1], StringComparison.OrdinalIgnoreCase));
|
||||
ContentPackage otherContentPackage = ContentPackage.AllPackages.FirstOrDefault(cp => cp.Name.Equals(splitPath[1], StringComparison.OrdinalIgnoreCase));
|
||||
if (otherContentPackage != null)
|
||||
{
|
||||
string otherPackageName = Path.GetDirectoryName(otherContentPackage.Path);
|
||||
|
||||
@@ -167,7 +167,7 @@ namespace Barotrauma.Networking
|
||||
bool prevCaptured = true;
|
||||
int captureTimer;
|
||||
|
||||
void UpdateCapture()
|
||||
private void UpdateCapture()
|
||||
{
|
||||
Array.Copy(uncompressedBuffer, 0, prevUncompressedBuffer, 0, VoipConfig.BUFFER_SIZE);
|
||||
Array.Clear(uncompressedBuffer, 0, VoipConfig.BUFFER_SIZE);
|
||||
@@ -273,6 +273,11 @@ namespace Barotrauma.Networking
|
||||
if (allowEnqueue || captureTimer > 0)
|
||||
{
|
||||
LastEnqueueAudio = DateTime.Now;
|
||||
if (GameMain.Client?.Character != null)
|
||||
{
|
||||
var messageType = !ForceLocal && ChatMessage.CanUseRadio(GameMain.Client.Character, out _) ? ChatMessageType.Radio : ChatMessageType.Default;
|
||||
GameMain.Client.Character.ShowSpeechBubble(1.25f, ChatMessage.MessageColor[(int)messageType]);
|
||||
}
|
||||
//encode audio and enqueue it
|
||||
lock (buffers)
|
||||
{
|
||||
|
||||
@@ -91,13 +91,13 @@ namespace Barotrauma
|
||||
if (userData == null) return;
|
||||
foreach (GUIComponent comp in listBox.Content.Children)
|
||||
{
|
||||
if (comp.UserData != userData) continue;
|
||||
GUITextBlock voteText = comp.FindChild("votes") as GUITextBlock;
|
||||
if (voteText == null)
|
||||
if (comp.UserData != userData) { continue; }
|
||||
if (!(comp.FindChild("votes") is GUITextBlock voteText))
|
||||
{
|
||||
voteText = new GUITextBlock(new RectTransform(new Point(30, comp.Rect.Height), comp.RectTransform, Anchor.CenterRight),
|
||||
"", textAlignment: Alignment.CenterRight)
|
||||
{
|
||||
Padding = Vector4.Zero,
|
||||
UserData = "votes"
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user