v1.6.17.0 (Unto the Breach update)

This commit is contained in:
Regalis11
2024-10-22 17:29:04 +03:00
parent e74b3cdb17
commit 6e6c17e100
417 changed files with 17166 additions and 5870 deletions
@@ -11,6 +11,9 @@ using System.Text;
namespace Barotrauma.Networking
{
[AttributeUsage(AttributeTargets.Property)]
public class DoNotSyncOverNetwork : Attribute { }
public enum SelectionMode
{
Manual = 0, Random = 1, Vote = 2
@@ -300,6 +303,7 @@ namespace Barotrauma.Networking
string typeName = SerializableProperty.GetSupportedTypeName(property.PropertyType);
if (typeName != null || property.PropertyType.IsEnum)
{
if (property.GetAttribute<DoNotSyncOverNetwork>() is not null) { continue; }
NetPropertyData netPropertyData = new NetPropertyData(this, property, typeName);
UInt32 key = ToolBoxCore.IdentifierToUint32Hash(netPropertyData.Name, md5);
if (key == 0) { key++; } //0 is reserved to indicate the end of the netproperties section of a message
@@ -500,13 +504,16 @@ namespace Barotrauma.Networking
/// <summary>
/// This is an optional setting for permadeath mode. When it's enabled, a player client whose character dies cannot
/// respawn or get a new character in any way in that game (unlike in normal permadeath mode), and can only spectate.
/// </summary>
/// NOTE: this setting will do nothing if respawn mode is not set to PermaDeath.
/// </summary>
public bool IronmanMode
{
get;
private set;
}
public bool IronmanModeActive => IronmanMode && respawnMode == RespawnMode.Permadeath;
[Serialize(60.0f, IsPropertySaveable.Yes)]
public float AutoRestartInterval
{
@@ -520,6 +527,20 @@ namespace Barotrauma.Networking
get;
set;
}
[Serialize(PvpTeamSelectionMode.PlayerPreference, IsPropertySaveable.Yes)]
public PvpTeamSelectionMode PvpTeamSelectionMode
{
get;
private set;
}
[Serialize(1, IsPropertySaveable.Yes)]
public int PvpAutoBalanceThreshold
{
get;
private set;
}
[Serialize(0.8f, IsPropertySaveable.Yes)]
public float StartWhenClientsReadyRatio
@@ -527,6 +548,41 @@ namespace Barotrauma.Networking
get;
private set;
}
[Serialize(0.0f, IsPropertySaveable.Yes)]
public float PvPStunResist
{
get;
private set;
}
[Serialize(false, IsPropertySaveable.Yes)]
public bool PvPSpawnMonsters
{
get;
private set;
}
[Serialize(true, IsPropertySaveable.Yes)]
public bool PvPSpawnWrecks
{
get;
private set;
}
[Serialize("Random", IsPropertySaveable.Yes)]
public Identifier Biome
{
get;
private set;
}
[Serialize("Random", IsPropertySaveable.Yes)]
public Identifier SelectedOutpostName
{
get;
private set;
}
private bool allowSpectating;
[Serialize(true, IsPropertySaveable.Yes)]
@@ -993,10 +1049,14 @@ namespace Barotrauma.Networking
}
[Serialize("All", IsPropertySaveable.Yes)]
public string MissionType
public string MissionTypes
{
get;
set;
get => string.Join(",", AllowedRandomMissionTypes.Select(t => t.ToIdentifier()));
set
{
AllowedRandomMissionTypes = value.Split(",").Select(t => t.ToIdentifier()).Distinct().ToList();
ValidateMissionTypes();
}
}
[Serialize(8, IsPropertySaveable.Yes)]
@@ -1006,10 +1066,13 @@ namespace Barotrauma.Networking
set { maxPlayers = MathHelper.Clamp(value, 1, NetConfig.MaxPlayers); }
}
public List<MissionType> AllowedRandomMissionTypes
/// <summary>
/// Wrapper for <see cref="MissionTypes"/>.
/// </summary>
public List<Identifier> AllowedRandomMissionTypes
{
get;
set;
private set;
}
[Serialize(60f * 60.0f, IsPropertySaveable.Yes)]
@@ -1035,6 +1098,24 @@ namespace Barotrauma.Networking
[Serialize(0f, IsPropertySaveable.Yes)]
public float NewCampaignDefaultSalary { get; set; }
[Serialize(true, IsPropertySaveable.Yes)]
public bool TrackOpponentInPvP { get; set; }
[Serialize(7, IsPropertySaveable.Yes)]
public int DisembarkPointAllowance { get; set; }
[Serialize("", IsPropertySaveable.Yes), DoNotSyncOverNetwork]
public Identifier[] SelectedCoalitionPerks { get; set; } = Array.Empty<Identifier>();
/// <summary>
/// The score required to win a PvP mission (if it is a mission with some scoring system, such as a deathmatch mission)
/// </summary>
[Serialize(200, IsPropertySaveable.Yes)]
public int WinScorePvP { get; set; }
[Serialize("", IsPropertySaveable.Yes), DoNotSyncOverNetwork]
public Identifier[] SelectedSeparatistsPerks { get; set; } = Array.Empty<Identifier>();
public CampaignSettings CampaignSettings { get; set; } = CampaignSettings.Empty;
private bool allowSubVoting;
@@ -1093,6 +1174,9 @@ namespace Barotrauma.Networking
public void SetPassword(string password)
{
this.password = string.IsNullOrEmpty(password) ? null : password;
#if SERVER
GameMain.Server?.ClearRecentlyDisconnectedClients();
#endif
}
public static byte[] SaltPassword(byte[] password, int salt)
@@ -1136,7 +1220,7 @@ namespace Barotrauma.Networking
=> monsterEnabled.Keys
.OrderBy(k => CharacterPrefab.Prefabs[k].UintIdentifier)
.ToImmutableArray();
public bool ReadMonsterEnabled(IReadMessage inc)
{
bool changed = false;
@@ -1214,6 +1298,75 @@ namespace Barotrauma.Networking
}
}
public void WritePerks(IWriteMessage msg)
{
List<DisembarkPerkPrefab> coalitionPerks = GetPerks(SelectedCoalitionPerks);
msg.WriteVariableUInt32((uint)coalitionPerks.Count);
foreach (DisembarkPerkPrefab perk in coalitionPerks)
{
msg.WriteUInt32(perk.UintIdentifier);
}
List<DisembarkPerkPrefab> separatistsPerks = GetPerks(SelectedSeparatistsPerks);
msg.WriteVariableUInt32((uint)separatistsPerks.Count);
foreach (DisembarkPerkPrefab perk in separatistsPerks)
{
msg.WriteUInt32(perk.UintIdentifier);
}
static List<DisembarkPerkPrefab> GetPerks(Identifier[] perkIdentifiers)
{
List<DisembarkPerkPrefab> perks = new();
foreach (Identifier perk in perkIdentifiers)
{
if (!DisembarkPerkPrefab.Prefabs.TryGet(perk, out var prefab)) { continue; }
perks.Add(prefab);
}
return perks;
}
}
public bool ReadPerks(IReadMessage msg)
{
uint coalitionCount = msg.ReadVariableUInt32();
Identifier[] newCoalitionPerks = new Identifier[coalitionCount];
for (int i = 0; i < coalitionCount; i++)
{
uint id = msg.ReadUInt32();
DisembarkPerkPrefab prefab = DisembarkPerkPrefab.Prefabs.Find(p => p.UintIdentifier == id);
if (prefab == null)
{
DebugConsole.ThrowError($"Perk not found: {id}");
continue;
}
newCoalitionPerks[i] = prefab.Identifier;
}
uint separatistsCount = msg.ReadVariableUInt32();
Identifier[] newSeparatistsPerks = new Identifier[separatistsCount];
for (int i = 0; i < separatistsCount; i++)
{
uint id = msg.ReadUInt32();
DisembarkPerkPrefab prefab = DisembarkPerkPrefab.Prefabs.Find(p => p.UintIdentifier == id);
if (prefab == null)
{
DebugConsole.ThrowError($"Perk not found: {id}");
continue;
}
newSeparatistsPerks[i] = prefab.Identifier;
}
bool changed = !SelectedCoalitionPerks.SequenceEqual(newCoalitionPerks) ||
!SelectedSeparatistsPerks.SequenceEqual(newSeparatistsPerks);
SelectedCoalitionPerks = newCoalitionPerks;
SelectedSeparatistsPerks = newSeparatistsPerks;
return changed;
}
public void ReadHiddenSubs(IReadMessage msg)
{
var subList = GameMain.NetLobbyScreen.GetSubList();
@@ -1285,5 +1438,34 @@ namespace Barotrauma.Networking
}
}
}
/// <summary>
/// Ensures that there's at least one mission type selected for both co-op and PvP game modes.
/// </summary>
private void ValidateMissionTypes()
{
ValidateMissionTypes(MissionPrefab.CoOpMissionClasses.Values);
ValidateMissionTypes(MissionPrefab.PvPMissionClasses.Values);
}
private void ValidateMissionTypes(IEnumerable<Type> availableMissionClasses)
{
if (AllowedRandomMissionTypes.Contains(Tags.MissionTypeAll)) { return; }
//no selectable mission types that match any of the available mission classes
//(e.g. no mission types that use pvp-specific mission classes)
if (MissionPrefab.GetAllMultiplayerSelectableMissionTypes().None(missionType =>
MissionPrefab.Prefabs.Any(p => p.Type == missionType && AllowedRandomMissionTypes.Contains(p.Type) && availableMissionClasses.Contains(p.MissionClass))))
{
var matchingMission = MissionPrefab.Prefabs.First(p => availableMissionClasses.Contains(p.MissionClass));
if (matchingMission == null)
{
DebugConsole.ThrowError($"No missions found for any of the available mission classes ({string.Join(",", availableMissionClasses)})");
}
else
{
AllowedRandomMissionTypes.Add(matchingMission.Type);
}
}
}
}
}