Build 1.1.4.0
This commit is contained in:
@@ -75,7 +75,7 @@ namespace Barotrauma.Networking
|
||||
float gain = 1.0f;
|
||||
float noiseGain = 0.0f;
|
||||
Vector3? position = null;
|
||||
if (character != null)
|
||||
if (character != null && !character.IsDead)
|
||||
{
|
||||
if (GameSettings.CurrentConfig.Audio.UseDirectionalVoiceChat)
|
||||
{
|
||||
|
||||
@@ -332,7 +332,6 @@ namespace Barotrauma.Networking
|
||||
FileSize = 0
|
||||
};
|
||||
|
||||
Md5Hash.Cache.Remove(directTransfer.FilePath);
|
||||
OnFinished(directTransfer);
|
||||
}
|
||||
break;
|
||||
@@ -414,7 +413,6 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
finishedTransfers.Add((transferId, Timing.TotalTime));
|
||||
StopTransfer(activeTransfer);
|
||||
Md5Hash.Cache.Remove(activeTransfer.FilePath);
|
||||
OnFinished(activeTransfer);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -76,6 +76,8 @@ namespace Barotrauma.Networking
|
||||
Interrupted
|
||||
}
|
||||
|
||||
private UInt16? debugStartGameCampaignSaveID;
|
||||
|
||||
private RoundInitStatus roundInitStatus = RoundInitStatus.NotStarted;
|
||||
|
||||
public bool RoundStarting => roundInitStatus == RoundInitStatus.Starting || roundInitStatus == RoundInitStatus.WaitingForStartGameFinalize;
|
||||
@@ -326,7 +328,7 @@ namespace Barotrauma.Networking
|
||||
return serverEndpoint switch
|
||||
{
|
||||
LidgrenEndpoint lidgrenEndpoint => new LidgrenClientPeer(lidgrenEndpoint, callbacks, ownerKey),
|
||||
SteamP2PEndpoint _ when ownerKey is Some<int> { Value: var key } => new SteamP2POwnerPeer(callbacks, key),
|
||||
SteamP2PEndpoint _ when ownerKey.TryUnwrap(out var key) => new SteamP2POwnerPeer(callbacks, key),
|
||||
SteamP2PEndpoint steamP2PServerEndpoint when ownerKey.IsNone() => new SteamP2PClientPeer(steamP2PServerEndpoint, callbacks),
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
@@ -859,17 +861,24 @@ namespace Barotrauma.Networking
|
||||
ContentFile file = ContentPackageManager.EnabledPackages.All
|
||||
.Select(p =>
|
||||
p.Files.FirstOrDefault(f => f.Path == filePath))
|
||||
.FirstOrDefault(f => !(f is null));
|
||||
.FirstOrDefault(f => f is not null);
|
||||
contentToPreload.AddIfNotNull(file);
|
||||
}
|
||||
|
||||
string campaignErrorInfo = string.Empty;
|
||||
if (GameMain.GameSession?.Campaign is MultiPlayerCampaign campaign)
|
||||
{
|
||||
campaignErrorInfo = $" Round start save ID: {debugStartGameCampaignSaveID}, last save id: {campaign.LastSaveID}, pending save id: {campaign.PendingSaveID}.";
|
||||
}
|
||||
|
||||
GameMain.GameSession.EventManager.PreloadContent(contentToPreload);
|
||||
|
||||
int subEqualityCheckValue = inc.ReadInt32();
|
||||
if (subEqualityCheckValue != (Submarine.MainSub?.Info?.EqualityCheckVal ?? 0))
|
||||
{
|
||||
string errorMsg = "Submarine equality check failed. The submarine loaded at your end doesn't match the one loaded by the server." +
|
||||
" There may have been an error in receiving the up-to-date submarine file from the server.";
|
||||
string errorMsg =
|
||||
"Submarine equality check failed. The submarine loaded at your end doesn't match the one loaded by the server. " +
|
||||
$"There may have been an error in receiving the up-to-date submarine file from the server. Round init status: {roundInitStatus}." + campaignErrorInfo;
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:SubsDontMatch" + Level.Loaded.Seed, GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
throw new Exception(errorMsg);
|
||||
}
|
||||
@@ -886,7 +895,7 @@ namespace Barotrauma.Networking
|
||||
$"Mission equality check failed. Mission count doesn't match the server. " +
|
||||
$"Server: {string.Join(", ", serverMissionIdentifiers)}, " +
|
||||
$"client: {string.Join(", ", GameMain.GameSession.GameMode.Missions.Select(m => m.Prefab.Identifier))}, " +
|
||||
$"game session: {string.Join(", ", GameMain.GameSession.Missions.Select(m => m.Prefab.Identifier))})";
|
||||
$"game session: {string.Join(", ", GameMain.GameSession.Missions.Select(m => m.Prefab.Identifier))}). Round init status: {roundInitStatus}." + campaignErrorInfo;
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:MissionsCountMismatch" + Level.Loaded.Seed, GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
throw new Exception(errorMsg);
|
||||
}
|
||||
@@ -899,7 +908,7 @@ namespace Barotrauma.Networking
|
||||
$"Mission equality check failed. The mission selected at your end doesn't match the one loaded by the server " +
|
||||
$"Server: {string.Join(", ", serverMissionIdentifiers)}, " +
|
||||
$"client: {string.Join(", ", GameMain.GameSession.GameMode.Missions.Select(m => m.Prefab.Identifier))}, " +
|
||||
$"game session: {string.Join(", ", GameMain.GameSession.Missions.Select(m => m.Prefab.Identifier))})";
|
||||
$"game session: {string.Join(", ", GameMain.GameSession.Missions.Select(m => m.Prefab.Identifier))}). Round init status: {roundInitStatus}." + campaignErrorInfo;
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:MissionsDontMatch" + Level.Loaded.Seed, GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
throw new Exception(errorMsg);
|
||||
}
|
||||
@@ -922,7 +931,7 @@ namespace Barotrauma.Networking
|
||||
", level value count: " + levelEqualityCheckValues.Count +
|
||||
", seed: " + Level.Loaded.Seed +
|
||||
", sub: " + Submarine.MainSub.Info.Name + " (" + Submarine.MainSub.Info.MD5Hash.ShortRepresentation + ")" +
|
||||
", mirrored: " + Level.Loaded.Mirrored + ").";
|
||||
", mirrored: " + Level.Loaded.Mirrored + "). Round init status: {roundInitStatus}." + campaignErrorInfo;
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameClient.StartGame:LevelsDontMatch" + Level.Loaded.Seed, GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
throw new Exception(errorMsg);
|
||||
}
|
||||
@@ -988,7 +997,7 @@ namespace Barotrauma.Networking
|
||||
GameMain.ModDownloadScreen.Reset();
|
||||
ContentPackageManager.EnabledPackages.Restore();
|
||||
|
||||
CampaignMode.StartRoundCancellationToken?.Cancel();
|
||||
GameMain.GameSession?.Campaign?.CancelStartRound();
|
||||
|
||||
if (SteamManager.IsInitialized)
|
||||
{
|
||||
@@ -1322,6 +1331,8 @@ namespace Barotrauma.Networking
|
||||
eventErrorWritten = false;
|
||||
GameMain.NetLobbyScreen.StopWaitingForStartRound();
|
||||
|
||||
debugStartGameCampaignSaveID = null;
|
||||
|
||||
while (CoroutineManager.IsCoroutineRunning("EndGame"))
|
||||
{
|
||||
EndCinematic?.Stop();
|
||||
@@ -1471,19 +1482,12 @@ namespace Barotrauma.Networking
|
||||
roundInitStatus = RoundInitStatus.Interrupted;
|
||||
yield return CoroutineStatus.Failure;
|
||||
}
|
||||
else if (campaign.Map == null)
|
||||
{
|
||||
GameStarted = true;
|
||||
DebugConsole.ThrowError("Failed to start campaign round (campaign map not loaded yet).");
|
||||
GameMain.NetLobbyScreen.Select();
|
||||
roundInitStatus = RoundInitStatus.Interrupted;
|
||||
yield return CoroutineStatus.Failure;
|
||||
}
|
||||
|
||||
if (NetIdUtils.IdMoreRecent(campaignSaveID, campaign.PendingSaveID))
|
||||
if (NetIdUtils.IdMoreRecent(campaign.PendingSaveID, campaign.LastSaveID) ||
|
||||
NetIdUtils.IdMoreRecent(campaignSaveID, campaign.PendingSaveID))
|
||||
{
|
||||
campaign.PendingSaveID = campaignSaveID;
|
||||
DateTime saveFileTimeOut = DateTime.Now + new TimeSpan(0,0,60);
|
||||
DateTime saveFileTimeOut = DateTime.Now + new TimeSpan(0, 0, 60);
|
||||
while (NetIdUtils.IdMoreRecent(campaignSaveID, campaign.LastSaveID))
|
||||
{
|
||||
if (DateTime.Now > saveFileTimeOut)
|
||||
@@ -1494,16 +1498,27 @@ namespace Barotrauma.Networking
|
||||
roundInitStatus = RoundInitStatus.Interrupted;
|
||||
yield return CoroutineStatus.Failure;
|
||||
}
|
||||
yield return new WaitForSeconds(0.1f);
|
||||
yield return new WaitForSeconds(0.1f);
|
||||
}
|
||||
}
|
||||
|
||||
if (campaign.Map == null)
|
||||
{
|
||||
GameStarted = true;
|
||||
DebugConsole.ThrowError("Failed to start campaign round (campaign map not loaded yet).");
|
||||
GameMain.NetLobbyScreen.Select();
|
||||
roundInitStatus = RoundInitStatus.Interrupted;
|
||||
yield return CoroutineStatus.Failure;
|
||||
}
|
||||
|
||||
campaign.Map.SelectLocation(selectedLocationIndex);
|
||||
|
||||
LevelData levelData = nextLocationIndex > -1 ?
|
||||
campaign.Map.Locations[nextLocationIndex].LevelData :
|
||||
campaign.Map.Connections[nextConnectionIndex].LevelData;
|
||||
|
||||
debugStartGameCampaignSaveID = campaign.LastSaveID;
|
||||
|
||||
if (roundSummary != null)
|
||||
{
|
||||
loadTask = campaign.SelectSummaryScreen(roundSummary, levelData, mirrorLevel, null);
|
||||
@@ -2587,31 +2602,24 @@ namespace Barotrauma.Networking
|
||||
public void WriteCharacterInfo(IWriteMessage msg, string newName = null)
|
||||
{
|
||||
msg.WriteBoolean(characterInfo == null);
|
||||
msg.WritePadBits();
|
||||
if (characterInfo == null) { return; }
|
||||
|
||||
msg.WriteString(newName ?? string.Empty);
|
||||
var head = characterInfo.Head;
|
||||
|
||||
msg.WriteByte((byte)characterInfo.Head.Preset.TagSet.Count);
|
||||
foreach (Identifier tag in characterInfo.Head.Preset.TagSet)
|
||||
{
|
||||
msg.WriteIdentifier(tag);
|
||||
}
|
||||
msg.WriteByte((byte)characterInfo.Head.HairIndex);
|
||||
msg.WriteByte((byte)characterInfo.Head.BeardIndex);
|
||||
msg.WriteByte((byte)characterInfo.Head.MoustacheIndex);
|
||||
msg.WriteByte((byte)characterInfo.Head.FaceAttachmentIndex);
|
||||
msg.WriteColorR8G8B8(characterInfo.Head.SkinColor);
|
||||
msg.WriteColorR8G8B8(characterInfo.Head.HairColor);
|
||||
msg.WriteColorR8G8B8(characterInfo.Head.FacialHairColor);
|
||||
var netInfo = new NetCharacterInfo(
|
||||
NewName: newName ?? string.Empty,
|
||||
Tags: head.Preset.TagSet.ToImmutableArray(),
|
||||
HairIndex: (byte)head.HairIndex,
|
||||
BeardIndex: (byte)head.BeardIndex,
|
||||
MoustacheIndex: (byte)head.MoustacheIndex,
|
||||
FaceAttachmentIndex: (byte)head.FaceAttachmentIndex,
|
||||
SkinColor: head.SkinColor,
|
||||
HairColor: head.HairColor,
|
||||
FacialHairColor: head.FacialHairColor,
|
||||
JobVariants: GameMain.NetLobbyScreen.JobPreferences.Select(NetJobVariant.FromJobVariant).ToImmutableArray());
|
||||
|
||||
var jobPreferences = GameMain.NetLobbyScreen.JobPreferences;
|
||||
int count = Math.Min(jobPreferences.Count, 3);
|
||||
msg.WriteByte((byte)count);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
msg.WriteIdentifier(jobPreferences[i].Prefab.Identifier);
|
||||
msg.WriteByte((byte)jobPreferences[i].Variant);
|
||||
}
|
||||
msg.WriteNetSerializableStruct(netInfo);
|
||||
}
|
||||
|
||||
public void Vote(VoteType voteType, object data)
|
||||
@@ -2623,7 +2631,13 @@ namespace Barotrauma.Networking
|
||||
using (var segmentTable = SegmentTableWriter<ClientNetSegment>.StartWriting(msg))
|
||||
{
|
||||
segmentTable.StartNewSegment(ClientNetSegment.Vote);
|
||||
Voting.ClientWrite(msg, voteType, data);
|
||||
bool succeeded = Voting.ClientWrite(msg, voteType, data);
|
||||
if (!succeeded)
|
||||
{
|
||||
throw new Exception(
|
||||
$"Failed to write vote of type {voteType}: " +
|
||||
$"data was of invalid type {data?.GetType().Name ?? "NULL"}");
|
||||
}
|
||||
}
|
||||
|
||||
ClientPeer.Send(msg, DeliveryMethod.Reliable);
|
||||
|
||||
@@ -92,10 +92,10 @@ namespace Barotrauma.Networking
|
||||
Name = GameMain.Client.Name,
|
||||
OwnerKey = ownerKey,
|
||||
SteamId = SteamManager.GetSteamId().Select(id => (AccountId)id),
|
||||
SteamAuthTicket = steamAuthTicket switch
|
||||
SteamAuthTicket = steamAuthTicket?.Data switch
|
||||
{
|
||||
null => Option<byte[]>.None(),
|
||||
var ticket => Option<byte[]>.Some(ticket.Data)
|
||||
var ticketData => Option<byte[]>.Some(ticketData)
|
||||
},
|
||||
GameVersion = GameMain.Version.ToString(),
|
||||
Language = GameSettings.CurrentConfig.Language.Value
|
||||
|
||||
+1
-1
@@ -156,7 +156,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
var packet = INetSerializableStruct.Read<ClientSteamTicketAndVersionPacket>(inc);
|
||||
|
||||
packet.SteamAuthTicket.TryUnwrap(out byte[] ticket);
|
||||
packet.SteamAuthTicket.TryUnwrap(out var ticket);
|
||||
|
||||
Steamworks.BeginAuthResult authSessionStartState = SteamManager.StartAuthSession(ticket, steamId);
|
||||
if (authSessionStartState != Steamworks.BeginAuthResult.OK)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#nullable enable
|
||||
|
||||
using Barotrauma.Extensions;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -69,6 +70,9 @@ namespace Barotrauma.Networking
|
||||
|
||||
[Serialize(PlayStyle.Casual, IsPropertySaveable.Yes)]
|
||||
public PlayStyle PlayStyle { get; set; }
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public LanguageIdentifier Language { get; set; }
|
||||
|
||||
public Version GameVersion { get; set; } = new Version(0, 0, 0, 0);
|
||||
|
||||
@@ -281,7 +285,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
float elementHeight = 0.075f;
|
||||
const float elementHeight = 0.075f;
|
||||
|
||||
// Spacing
|
||||
new GUIFrame(new RectTransform(new Vector2(1.0f, 0.025f), content.RectTransform), style: null);
|
||||
@@ -294,6 +298,11 @@ namespace Barotrauma.Networking
|
||||
serverMsg.Content.RectTransform.SizeChanged += () => { msgText.CalculateHeightFromText(); };
|
||||
msgText.RectTransform.SizeChanged += () => { serverMsg.UpdateScrollBarSize(); };
|
||||
|
||||
var languageLabel = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), content.RectTransform), TextManager.Get("Language"));
|
||||
new GUITextBlock(new RectTransform(Vector2.One, languageLabel.RectTransform),
|
||||
ServerLanguageOptions.Options.FirstOrNull(o => o.Identifier == Language)?.Label ?? TextManager.Get("Unknown"),
|
||||
textAlignment: Alignment.Right);
|
||||
|
||||
var gameMode = new GUITextBlock(new RectTransform(new Vector2(1.0f, elementHeight), content.RectTransform), TextManager.Get("GameMode"));
|
||||
new GUITextBlock(new RectTransform(Vector2.One, gameMode.RectTransform),
|
||||
TextManager.Get(GameMode.IsEmpty ? "Unknown" : "GameMode." + GameMode).Fallback(GameMode.Value),
|
||||
@@ -363,7 +372,7 @@ namespace Barotrauma.Networking
|
||||
packageText.Selected = true;
|
||||
}
|
||||
//workshop download link found
|
||||
else if (package.Id is Some<ContentPackageId> { Value: var ugcId } && ugcId is SteamWorkshopId)
|
||||
else if (package.Id.TryUnwrap(out var ugcId) && ugcId is SteamWorkshopId)
|
||||
{
|
||||
packageText.ToolTip = TextManager.GetWithVariable("ServerListIncompatibleContentPackageWorkshopAvailable", "[contentpackage]", package.Name);
|
||||
}
|
||||
@@ -417,8 +426,9 @@ namespace Barotrauma.Networking
|
||||
GameMode = valueGetter("gamemode")?.ToIdentifier() ?? Identifier.Empty;
|
||||
if (Enum.TryParse(valueGetter("traitors"), out YesNoMaybe traitorsEnabled)) { TraitorsEnabled = traitorsEnabled; }
|
||||
if (Enum.TryParse(valueGetter("playstyle"), out PlayStyle playStyle)) { PlayStyle = playStyle; }
|
||||
Language = valueGetter("language")?.ToLanguageIdentifier() ?? LanguageIdentifier.None;
|
||||
|
||||
ContentPackages = ExtractContentPackageInfo(valueGetter).ToImmutableArray();
|
||||
ContentPackages = ExtractContentPackageInfo(ServerName, valueGetter).ToImmutableArray();
|
||||
|
||||
bool getBool(string key)
|
||||
{
|
||||
@@ -427,8 +437,34 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
private static ContentPackageInfo[] ExtractContentPackageInfo(Func<string, string?> valueGetter)
|
||||
private static ContentPackageInfo[] ExtractContentPackageInfo(string serverName, Func<string, string?> valueGetter)
|
||||
{
|
||||
//workaround to ServerRules queries truncating the values to 255 bytes
|
||||
int individualPackageIndex = 0;
|
||||
string? individualPackage = valueGetter($"contentpackage{individualPackageIndex}");
|
||||
if (!individualPackage.IsNullOrEmpty())
|
||||
{
|
||||
List<ContentPackageInfo> contentPackages = new List<ContentPackageInfo>();
|
||||
do
|
||||
{
|
||||
string[] splitPackageInfo = individualPackage.Split(',');
|
||||
if (splitPackageInfo.Length != 3)
|
||||
{
|
||||
DebugConsole.Log(
|
||||
$"Error in a server's content package list: malformed content package info ({individualPackage}).");
|
||||
return Array.Empty<ContentPackageInfo>();
|
||||
}
|
||||
string name = splitPackageInfo[0];
|
||||
string hash = splitPackageInfo[1];
|
||||
ulong.TryParse(splitPackageInfo[2], out ulong id);
|
||||
contentPackages.Add(new ContentPackageInfo(name, hash, Option<ContentPackageId>.Some(new SteamWorkshopId(id))));
|
||||
|
||||
individualPackageIndex++;
|
||||
individualPackage = valueGetter($"contentpackage{individualPackageIndex}");
|
||||
} while (!individualPackage.IsNullOrEmpty());
|
||||
return contentPackages.ToArray();
|
||||
}
|
||||
|
||||
string? joinedNames = valueGetter("contentpackage");
|
||||
string? joinedHashes = valueGetter("contentpackagehash");
|
||||
string? joinedWorkshopIds = valueGetter("contentpackageid");
|
||||
@@ -438,9 +474,11 @@ namespace Barotrauma.Networking
|
||||
#warning TODO: genericize
|
||||
ulong[] contentPackageIds = joinedWorkshopIds.IsNullOrEmpty() ? new ulong[1] : SteamManager.ParseWorkshopIds(joinedWorkshopIds).ToArray();
|
||||
|
||||
if (contentPackageNames.Length != contentPackageHashes.Length
|
||||
|| contentPackageHashes.Length != contentPackageIds.Length)
|
||||
if (contentPackageNames.Length != contentPackageHashes.Length || contentPackageHashes.Length != contentPackageIds.Length)
|
||||
{
|
||||
DebugConsole.Log(
|
||||
$"The number of names, hashes and Workshop IDs on server \"{serverName}\"" +
|
||||
$" doesn't match: {contentPackageNames.Length} names ({string.Join(", ", contentPackageNames)}), {contentPackageHashes.Length} hashes, {contentPackageIds.Length} ids)");
|
||||
return Array.Empty<ContentPackageInfo>();
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
private static Option<ServerInfo> InfoFromListEntry(Steamworks.Data.ServerInfo entry) =>
|
||||
entry.Name.IsNullOrEmpty()
|
||||
entry.Name.IsNullOrEmpty() || entry.Address is null
|
||||
? Option<ServerInfo>.None()
|
||||
: Option<ServerInfo>.Some(new ServerInfo(new LidgrenEndpoint(entry.Address, entry.ConnectionPort))
|
||||
{
|
||||
|
||||
+2
-2
@@ -71,10 +71,10 @@ namespace Barotrauma
|
||||
|
||||
foreach (var lobby in lobbies)
|
||||
{
|
||||
string lobbyOwnerStr = lobby.GetData("lobbyowner");
|
||||
string lobbyOwnerStr = lobby.GetData("lobbyowner") ?? "";
|
||||
lobbyQuery = lobbyQuery.WithoutKeyValue("lobbyowner", lobbyOwnerStr);
|
||||
|
||||
string serverName = lobby.GetData("name");
|
||||
string serverName = lobby.GetData("name") ?? "";
|
||||
if (string.IsNullOrEmpty(serverName)) { continue; }
|
||||
|
||||
var ownerId = SteamId.Parse(lobbyOwnerStr);
|
||||
|
||||
@@ -3,11 +3,15 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using Barotrauma.Steam;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
partial class ServerSettings : ISerializableEntity
|
||||
{
|
||||
private static readonly LocalizedString packetAmountTooltip = TextManager.Get("ServerSettingsMaxPacketAmountTooltip");
|
||||
private static readonly RichString packetAmountTooltipWarning = RichString.Rich($"{packetAmountTooltip}\n\n‖color:gui.red‖{TextManager.Get("PacketLimitWarning")}‖end‖");
|
||||
|
||||
partial class NetPropertyData
|
||||
{
|
||||
public GUIComponent GUIComponent;
|
||||
@@ -27,7 +31,15 @@ namespace Barotrauma.Networking
|
||||
if (GUIComponent == null) return null;
|
||||
else if (GUIComponent is GUITickBox tickBox) return tickBox.Selected;
|
||||
else if (GUIComponent is GUITextBox textBox) return textBox.Text;
|
||||
else if (GUIComponent is GUIScrollBar scrollBar) return scrollBar.BarScrollValue;
|
||||
else if (GUIComponent is GUIScrollBar scrollBar)
|
||||
{
|
||||
if (property.PropertyType == typeof(int))
|
||||
{
|
||||
return (int)MathF.Floor(scrollBar.BarScrollValue);
|
||||
}
|
||||
|
||||
return scrollBar.BarScrollValue;
|
||||
}
|
||||
else if (GUIComponent is GUIRadioButtonGroup radioButtonGroup) return radioButtonGroup.Selected;
|
||||
else if (GUIComponent is GUIDropDown dropdown) return dropdown.SelectedData;
|
||||
else if (GUIComponent is GUINumberInput numInput)
|
||||
@@ -43,9 +55,9 @@ namespace Barotrauma.Networking
|
||||
else if (GUIComponent is GUITextBox textBox) textBox.Text = (string)value;
|
||||
else if (GUIComponent is GUIScrollBar scrollBar)
|
||||
{
|
||||
if (value.GetType() == typeof(int))
|
||||
if (value is int i)
|
||||
{
|
||||
scrollBar.BarScrollValue = (int)value;
|
||||
scrollBar.BarScrollValue = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -78,7 +90,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
private Dictionary<Identifier, bool> tempMonsterEnabled;
|
||||
|
||||
|
||||
partial void InitProjSpecific()
|
||||
{
|
||||
var properties = TypeDescriptor.GetProperties(GetType()).Cast<PropertyDescriptor>();
|
||||
@@ -367,6 +379,15 @@ namespace Barotrauma.Networking
|
||||
|
||||
//***********************************************
|
||||
|
||||
// Language
|
||||
new GUITextBlock(new RectTransform(new Vector2(1.0f, 0.0f), serverTab.RectTransform), TextManager.Get("Language"), font: GUIStyle.SubHeadingFont);
|
||||
var languageDD = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.02f), serverTab.RectTransform));
|
||||
foreach (var language in ServerLanguageOptions.Options)
|
||||
{
|
||||
languageDD.AddItem(language.Label, language.Identifier);
|
||||
}
|
||||
GetPropertyData(nameof(Language)).AssignGUIComponent(languageDD);
|
||||
|
||||
//changing server visibility on the fly is not supported in dedicated servers
|
||||
if (GameMain.Client?.ClientPeer is not LidgrenClientPeer)
|
||||
{
|
||||
@@ -931,11 +952,58 @@ namespace Barotrauma.Networking
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
GUILayoutGroup karmaAndDosLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.2f), antigriefingTab.RectTransform), isHorizontal: false);
|
||||
GUILayoutGroup lowerLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.5f), karmaAndDosLayout.RectTransform), isHorizontal: true);
|
||||
GUILayoutGroup upperLayout = new GUILayoutGroup(new RectTransform(new Vector2(1f, 0.5f), karmaAndDosLayout.RectTransform), isHorizontal: true);
|
||||
|
||||
// karma --------------------------------------------------------------------------
|
||||
|
||||
var karmaBox = new GUITickBox(new RectTransform(new Vector2(1.0f, 0.05f), antigriefingTab.RectTransform), TextManager.Get("ServerSettingsUseKarma"));
|
||||
var karmaBox = new GUITickBox(new RectTransform(new Vector2(0.5f, 1f), upperLayout.RectTransform), TextManager.Get("ServerSettingsUseKarma"));
|
||||
GetPropertyData(nameof(KarmaEnabled)).AssignGUIComponent(karmaBox);
|
||||
|
||||
var enableDosProtection = new GUITickBox(new RectTransform(new Vector2(0.5f, 1f), upperLayout.RectTransform), TextManager.Get("ServerSettingsEnableDoSProtection"))
|
||||
{
|
||||
ToolTip = TextManager.Get("ServerSettingsEnableDoSProtectionTooltip")
|
||||
};
|
||||
GetPropertyData(nameof(EnableDoSProtection)).AssignGUIComponent(enableDosProtection);
|
||||
|
||||
CreateLabeledSlider(lowerLayout, "ServerSettingsMaxPacketAmount", out GUIScrollBar maxPacketSlider, out GUITextBlock maxPacketSliderLabel);
|
||||
LocalizedString maxPacketCountLabel = maxPacketSliderLabel.Text;
|
||||
maxPacketSlider.Step = 0.001f;
|
||||
maxPacketSlider.Range = new Vector2(PacketLimitMin, PacketLimitMax);
|
||||
maxPacketSlider.ToolTip = packetAmountTooltip;
|
||||
maxPacketSlider.OnMoved = (scrollBar, _) =>
|
||||
{
|
||||
GUITextBlock textBlock = (GUITextBlock)scrollBar.UserData;
|
||||
int value = (int)MathF.Floor(scrollBar.BarScrollValue);
|
||||
|
||||
LocalizedString valueText = value > PacketLimitMin
|
||||
? value.ToString()
|
||||
: TextManager.Get("ServerSettingsNoLimit");
|
||||
|
||||
switch (value)
|
||||
{
|
||||
case <= PacketLimitMin:
|
||||
textBlock.TextColor = GUIStyle.Green;
|
||||
scrollBar.ToolTip = packetAmountTooltip;
|
||||
break;
|
||||
case < PacketLimitWarning:
|
||||
textBlock.TextColor = GUIStyle.Red;
|
||||
scrollBar.ToolTip = packetAmountTooltipWarning;
|
||||
break;
|
||||
default:
|
||||
textBlock.TextColor = GUIStyle.TextColorNormal;
|
||||
scrollBar.ToolTip = packetAmountTooltip;
|
||||
break;
|
||||
}
|
||||
|
||||
textBlock.Text = $"{maxPacketCountLabel} {valueText}";
|
||||
return true;
|
||||
};
|
||||
GetPropertyData(nameof(MaxPacketAmount)).AssignGUIComponent(maxPacketSlider);
|
||||
maxPacketSlider.OnMoved(maxPacketSlider, maxPacketSlider.BarScroll);
|
||||
|
||||
karmaPresetDD = new GUIDropDown(new RectTransform(new Vector2(1.0f, 0.05f), antigriefingTab.RectTransform));
|
||||
foreach (string karmaPreset in GameMain.NetworkMember.KarmaManager.Presets.Keys)
|
||||
{
|
||||
|
||||
@@ -276,6 +276,8 @@ namespace Barotrauma.Networking
|
||||
if (GameMain.Client?.Character != null)
|
||||
{
|
||||
var messageType = !ForceLocal && ChatMessage.CanUseRadio(GameMain.Client.Character, out _) ? ChatMessageType.Radio : ChatMessageType.Default;
|
||||
if (GameMain.Client.Character.IsDead) { messageType = ChatMessageType.Dead; }
|
||||
|
||||
GameMain.Client.Character.ShowSpeechBubble(1.25f, ChatMessage.MessageColor[(int)messageType]);
|
||||
}
|
||||
//encode audio and enqueue it
|
||||
|
||||
@@ -116,7 +116,9 @@ namespace Barotrauma.Networking
|
||||
bool spectating = Character.Controlled == null;
|
||||
float rangeMultiplier = spectating ? 2.0f : 1.0f;
|
||||
WifiComponent radio = null;
|
||||
var messageType = !client.VoipQueue.ForceLocal && ChatMessage.CanUseRadio(client.Character, out radio) ? ChatMessageType.Radio : ChatMessageType.Default;
|
||||
var messageType =
|
||||
!client.VoipQueue.ForceLocal && ChatMessage.CanUseRadio(client.Character, out radio) && ChatMessage.CanUseRadio(Character.Controlled) ?
|
||||
ChatMessageType.Radio : ChatMessageType.Default;
|
||||
client.Character.ShowSpeechBubble(1.25f, ChatMessage.MessageColor[(int)messageType]);
|
||||
|
||||
client.VoipSound.UseRadioFilter = messageType == ChatMessageType.Radio && !GameSettings.CurrentConfig.Audio.DisableVoiceChatFilters;
|
||||
@@ -144,7 +146,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
if ((client.VoipSound.CurrentAmplitude * client.VoipSound.Gain * GameMain.SoundManager.GetCategoryGainMultiplier("voip")) > 0.1f) //TODO: might need to tweak
|
||||
{
|
||||
if (client.Character != null && !client.Character.Removed)
|
||||
if (client.Character != null && !client.Character.Removed && !client.Character.IsDead)
|
||||
{
|
||||
Vector3 clientPos = new Vector3(client.Character.WorldPosition.X, client.Character.WorldPosition.Y, 0.0f);
|
||||
Vector3 listenerPos = GameMain.SoundManager.ListenerPosition;
|
||||
|
||||
@@ -13,13 +13,11 @@ namespace Barotrauma
|
||||
{
|
||||
public SubmarineInfo SubmarineInfo { get; set; }
|
||||
public bool TransferItems { get; set; }
|
||||
public int DeliveryFee { get; set; }
|
||||
|
||||
public SubmarineVoteInfo(SubmarineInfo submarineInfo, bool transferItems, int deliveryFee)
|
||||
public SubmarineVoteInfo(SubmarineInfo submarineInfo, bool transferItems)
|
||||
{
|
||||
SubmarineInfo = submarineInfo;
|
||||
TransferItems = transferItems;
|
||||
DeliveryFee = deliveryFee;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,64 +126,72 @@ namespace Barotrauma
|
||||
UpdateVoteTexts(connectedClients, VoteType.Sub);
|
||||
}
|
||||
|
||||
public void ClientWrite(IWriteMessage msg, VoteType voteType, object data)
|
||||
/// <summary>
|
||||
/// Returns true if the given data is valid for the given vote type,
|
||||
/// returns false otherwise. If it returns false, the message must
|
||||
/// be discarded or reset by the caller, as it is now malformed :)
|
||||
/// </summary>
|
||||
public bool ClientWrite(IWriteMessage msg, VoteType voteType, object data)
|
||||
{
|
||||
msg.WriteByte((byte)voteType);
|
||||
|
||||
switch (voteType)
|
||||
{
|
||||
case VoteType.Sub:
|
||||
if (!(data is SubmarineInfo sub)) { return; }
|
||||
if (data is not SubmarineInfo sub) { return false; }
|
||||
msg.WriteInt32(sub.EqualityCheckVal);
|
||||
if (sub.EqualityCheckVal == 0)
|
||||
if (sub.EqualityCheckVal <= 0)
|
||||
{
|
||||
//sub doesn't exist client-side, use hash to let the server know which one we voted for
|
||||
msg.WriteString(sub.MD5Hash.StringRepresentation);
|
||||
}
|
||||
break;
|
||||
case VoteType.Mode:
|
||||
if (!(data is GameModePreset gameMode)) { return; }
|
||||
if (data is not GameModePreset gameMode) { return false; }
|
||||
msg.WriteIdentifier(gameMode.Identifier);
|
||||
break;
|
||||
case VoteType.EndRound:
|
||||
if (!(data is bool)) { return; }
|
||||
msg.WriteBoolean((bool)data);
|
||||
if (data is not bool endRound) { return false; }
|
||||
msg.WriteBoolean(endRound);
|
||||
break;
|
||||
case VoteType.Kick:
|
||||
if (!(data is Client votedClient)) { return; }
|
||||
if (data is not Client votedClient) { return false; }
|
||||
|
||||
msg.WriteByte(votedClient.SessionId);
|
||||
break;
|
||||
case VoteType.StartRound:
|
||||
if (!(data is bool)) { return; }
|
||||
msg.WriteBoolean((bool)data);
|
||||
if (data is not bool startRound) { return false; }
|
||||
msg.WriteBoolean(startRound);
|
||||
break;
|
||||
case VoteType.PurchaseAndSwitchSub:
|
||||
case VoteType.PurchaseSub:
|
||||
case VoteType.SwitchSub:
|
||||
if (data is (SubmarineInfo voteSub, bool transferItems))
|
||||
{
|
||||
//initiate sub vote
|
||||
msg.WriteBoolean(true);
|
||||
msg.WriteString(voteSub.Name);
|
||||
msg.WriteBoolean(transferItems);
|
||||
}
|
||||
else
|
||||
switch (data)
|
||||
{
|
||||
// vote
|
||||
if (!(data is int)) { return; }
|
||||
msg.WriteBoolean(false);
|
||||
msg.WriteInt32((int)data);
|
||||
case (SubmarineInfo voteSub, bool transferItems):
|
||||
//initiate sub vote
|
||||
msg.WriteBoolean(true);
|
||||
msg.WriteString(voteSub.Name);
|
||||
msg.WriteBoolean(transferItems);
|
||||
break;
|
||||
case int vote:
|
||||
// vote
|
||||
msg.WriteBoolean(false);
|
||||
msg.WriteInt32(vote);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case VoteType.TransferMoney:
|
||||
if (!(data is int)) { return; }
|
||||
if (data is not int money) { return false; }
|
||||
msg.WriteBoolean(false); //not initiating a vote
|
||||
msg.WriteInt32((int)data);
|
||||
msg.WriteInt32(money);
|
||||
break;
|
||||
}
|
||||
|
||||
msg.WritePadBits();
|
||||
return true;
|
||||
}
|
||||
|
||||
public void ClientRead(IReadMessage inc)
|
||||
@@ -322,33 +328,34 @@ namespace Barotrauma
|
||||
case VoteType.PurchaseAndSwitchSub:
|
||||
case VoteType.SwitchSub:
|
||||
string subName2 = inc.ReadString();
|
||||
var submarineInfo = GameMain.GameSession.OwnedSubmarines.FirstOrDefault(s => s.Name == subName2) ?? GameMain.Client.ServerSubmarines.FirstOrDefault(s => s.Name == subName2);
|
||||
bool transferItems = inc.ReadBoolean();
|
||||
int deliveryFee = inc.ReadInt16();
|
||||
if (submarineInfo == null)
|
||||
if (GameMain.GameSession != null)
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to find a matching submarine, vote aborted");
|
||||
return;
|
||||
var submarineInfo = GameMain.GameSession.OwnedSubmarines.FirstOrDefault(s => s.Name == subName2) ?? GameMain.Client.ServerSubmarines.FirstOrDefault(s => s.Name == subName2);
|
||||
if (submarineInfo == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to find a matching submarine, vote aborted");
|
||||
return;
|
||||
}
|
||||
submarineVoteInfo = new SubmarineVoteInfo(submarineInfo, transferItems);
|
||||
}
|
||||
submarineVoteInfo = new SubmarineVoteInfo(submarineInfo, transferItems, deliveryFee);
|
||||
break;
|
||||
}
|
||||
|
||||
GameMain.Client.VotingInterface?.EndVote(passed, yesClientCount, noClientCount);
|
||||
|
||||
GameMain.Client.VotingInterface?.EndVote(passed, yesClientCount, noClientCount);
|
||||
if (passed && submarineVoteInfo.SubmarineInfo is { } subInfo)
|
||||
{
|
||||
switch (voteType)
|
||||
{
|
||||
case VoteType.PurchaseAndSwitchSub:
|
||||
GameMain.GameSession.PurchaseSubmarine(subInfo);
|
||||
GameMain.GameSession.SwitchSubmarine(subInfo, submarineVoteInfo.TransferItems, 0);
|
||||
GameMain.GameSession.SwitchSubmarine(subInfo, submarineVoteInfo.TransferItems);
|
||||
break;
|
||||
case VoteType.PurchaseSub:
|
||||
GameMain.GameSession.PurchaseSubmarine(subInfo);
|
||||
break;
|
||||
case VoteType.SwitchSub:
|
||||
GameMain.GameSession.SwitchSubmarine(subInfo, submarineVoteInfo.TransferItems, submarineVoteInfo.DeliveryFee);
|
||||
GameMain.GameSession.SwitchSubmarine(subInfo, submarineVoteInfo.TransferItems);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user