Unstable 1.1.14.0

This commit is contained in:
Markus Isberg
2023-10-02 16:43:54 +03:00
parent 94f5a93a0c
commit cf8f0de659
606 changed files with 21906 additions and 11456 deletions
@@ -42,8 +42,6 @@ namespace Barotrauma.Networking
public string RejectedName;
public int RoundsSincePlayedAsTraitor;
public float KickAFKTimer;
public double MidRoundSyncTimeOut;
@@ -49,7 +49,7 @@ namespace Barotrauma.Networking
{
await Task.Yield();
string dir = mod.Dir;
SaveUtil.CompressDirectory(dir, GetCompressedModPath(mod), fileName => { });
SaveUtil.CompressDirectory(dir, GetCompressedModPath(mod));
}
private void DeleteDir()
@@ -74,13 +74,21 @@ namespace Barotrauma.Networking
private bool initiatedStartGame;
private CoroutineHandle startGameCoroutine;
public TraitorManager TraitorManager;
private readonly ServerEntityEventManager entityEventManager;
public FileSender FileSender { get; private set; }
public ModSender ModSender { get; private set; }
private TraitorManager traitorManager;
public TraitorManager TraitorManager
{
get
{
traitorManager ??= new TraitorManager(this);
return traitorManager;
}
}
#if DEBUG
public void PrintSenderTransters()
@@ -358,22 +366,31 @@ namespace Barotrauma.Networking
for (int i = Character.CharacterList.Count - 1; i >= 0; i--)
{
Character character = Character.CharacterList[i];
if (character.IsDead || !character.ClientDisconnected) { continue; }
character.KillDisconnectedTimer += deltaTime;
character.SetStun(1.0f);
if (!character.ClientDisconnected) { continue; }
Client owner = connectedClients.Find(c => (c.Character == null || c.Character == character) && character.IsClientOwner(c));
if ((OwnerConnection == null || owner?.Connection != OwnerConnection) && character.KillDisconnectedTimer > ServerSettings.KillDisconnectedTime)
if (!character.IsDead)
{
character.Kill(CauseOfDeathType.Disconnected, null);
continue;
}
character.KillDisconnectedTimer += deltaTime;
character.SetStun(1.0f);
if (owner != null && owner.InGame && !owner.NeedsMidRoundSync &&
(!ServerSettings.AllowSpectating || !owner.SpectateOnly))
if ((OwnerConnection == null || owner?.Connection != OwnerConnection) && character.KillDisconnectedTimer > ServerSettings.KillDisconnectedTime)
{
character.Kill(CauseOfDeathType.Disconnected, null);
continue;
}
if (owner != null && owner.InGame && !owner.NeedsMidRoundSync &&
(!ServerSettings.AllowSpectating || !owner.SpectateOnly))
{
SetClientCharacter(owner, character);
}
}
else if (owner != null &&
character.CauseOfDeath?.Type == CauseOfDeathType.Disconnected &&
character.CharacterHealth.VitalityDisregardingDeath > 0)
{
SetClientCharacter(owner, character);
character.Revive(removeAfflictions: false);
}
}
@@ -412,12 +429,7 @@ namespace Barotrauma.Networking
}
float endRoundDelay = 1.0f;
if (TraitorManager?.ShouldEndRound ?? false)
{
endRoundDelay = 5.0f;
endRoundTimer += deltaTime;
}
else if (ServerSettings.AutoRestart && isCrewDead)
if (ServerSettings.AutoRestart && isCrewDead)
{
endRoundDelay = 5.0f;
endRoundTimer += deltaTime;
@@ -452,11 +464,7 @@ namespace Barotrauma.Networking
if (endRoundTimer >= endRoundDelay)
{
if (TraitorManager?.ShouldEndRound ?? false)
{
Log("Ending round (a traitor completed their mission)", ServerLog.MessageType.ServerMessage);
}
else if (ServerSettings.AutoRestart && isCrewDead)
if (ServerSettings.AutoRestart && isCrewDead)
{
Log("Ending round (entire crew dead)", ServerLog.MessageType.ServerMessage);
}
@@ -830,6 +838,9 @@ namespace Barotrauma.Networking
case ClientPacketHeader.MEDICAL:
ReadMedicalMessage(inc, connectedClient);
break;
case ClientPacketHeader.CIRCUITBOX:
ReadCircuitBoxMessage(inc, connectedClient);
break;
case ClientPacketHeader.READY_CHECK:
ReadyCheck.ServerRead(inc, connectedClient);
break;
@@ -1299,6 +1310,22 @@ namespace Barotrauma.Networking
}
}
private static void ReadCircuitBoxMessage(IReadMessage inc, Client sender)
{
var header = INetSerializableStruct.Read<NetCircuitBoxHeader>(inc);
INetSerializableStruct data = header.Opcode switch
{
CircuitBoxOpcode.Cursor => INetSerializableStruct.Read<NetCircuitBoxCursorInfo>(inc),
_ => throw new ArgumentOutOfRangeException(nameof(header.Opcode), header.Opcode, "This data cannot be handled using direct network messages.")
};
if (header.FindTarget().TryUnwrap(out var box))
{
box.ServerRead(data, sender);
}
}
private void ReadReadyToSpawnMessage(IReadMessage inc, Client sender)
{
sender.SpectateOnly = inc.ReadBoolean() && (ServerSettings.AllowSpectating || sender.Connection == OwnerConnection);
@@ -1775,7 +1802,7 @@ namespace Barotrauma.Networking
while (!c.NeedsMidRoundSync && c.PendingPositionUpdates.Count > 0)
{
var entity = c.PendingPositionUpdates.Peek();
if (!(entity is IServerPositionSync entityPositionSync) ||
if (entity is not IServerPositionSync entityPositionSync ||
entity.Removed ||
(entity is Item item && float.IsInfinity(item.PositionUpdateInterval)))
{
@@ -1957,7 +1984,8 @@ namespace Barotrauma.Networking
outmsg.WriteBoolean(ServerSettings.AllowSpectating);
outmsg.WriteRangedInteger((int)ServerSettings.TraitorsEnabled, 0, 2);
outmsg.WriteSingle(ServerSettings.TraitorProbability);
outmsg.WriteRangedInteger(ServerSettings.TraitorDangerLevel, TraitorEventPrefab.MinDangerLevel, TraitorEventPrefab.MaxDangerLevel);
outmsg.WriteRangedInteger((int)GameMain.NetLobbyScreen.MissionType, 0, (int)MissionType.All);
@@ -2212,6 +2240,7 @@ namespace Barotrauma.Networking
//don't instantiate a new gamesession if we're playing a campaign
if (campaign == null || GameMain.GameSession == null)
{
traitorManager = new TraitorManager(this);
GameMain.GameSession = new GameSession(selectedSub, "", selectedMode, settings, GameMain.NetLobbyScreen.LevelSeed, missionType: GameMain.NetLobbyScreen.MissionType);
}
else
@@ -2509,16 +2538,8 @@ namespace Barotrauma.Networking
}
}
TraitorManager = null;
if (ServerSettings.TraitorsEnabled == YesNoMaybe.Yes ||
(ServerSettings.TraitorsEnabled == YesNoMaybe.Maybe && Rand.Range(0.0f, 1.0f) < 0.5f))
{
if (!(GameMain.GameSession?.GameMode is CampaignMode))
{
TraitorManager = new TraitorManager();
TraitorManager.Start(this);
}
}
TraitorManager.Initialize(GameMain.GameSession.EventManager, Level.Loaded);
TraitorManager.Enabled = Rand.Range(0.0f, 1.0f) < ServerSettings.TraitorProbability;
GameAnalyticsManager.AddDesignEvent("Traitors:" + (TraitorManager == null ? "Disabled" : "Enabled"));
@@ -2562,7 +2583,6 @@ namespace Barotrauma.Networking
msg.WriteBoolean(ServerSettings.AllowRewiring);
msg.WriteBoolean(ServerSettings.AllowFriendlyFire);
msg.WriteBoolean(ServerSettings.LockAllDefaultWires);
msg.WriteBoolean(ServerSettings.AllowRagdollButton);
msg.WriteBoolean(ServerSettings.AllowLinkingWifiToChat);
msg.WriteInt32(ServerSettings.MaximumMoneyTransferRequest);
msg.WriteBoolean(IsUsingRespawnShuttle());
@@ -2685,13 +2705,12 @@ namespace Barotrauma.Networking
}
string endMessage = TextManager.FormatServerMessage("RoundSummaryRoundHasEnded");
var traitorResults = TraitorManager?.GetEndResults() ?? new List<TraitorMissionResult>();
List<Mission> missions = GameMain.GameSession.Missions.ToList();
if (GameMain.GameSession is { IsRunning: true })
{
GameMain.GameSession.EndRound(endMessage, traitorResults);
GameMain.GameSession.EndRound(endMessage);
}
TraitorManager.TraitorResults? traitorResults = traitorManager?.GetEndResults() ?? null;
endRoundTimer = 0.0f;
@@ -2736,10 +2755,10 @@ namespace Barotrauma.Networking
}
msg.WriteByte(GameMain.GameSession?.WinningTeam == null ? (byte)0 : (byte)GameMain.GameSession.WinningTeam);
msg.WriteByte((byte)traitorResults.Count);
foreach (var traitorResult in traitorResults)
msg.WriteBoolean(traitorResults.HasValue);
if (traitorResults.HasValue)
{
traitorResult.ServerWrite(msg);
msg.WriteNetSerializableStruct(traitorResults.Value);
}
foreach (Client client in connectedClients)
@@ -2788,13 +2807,14 @@ namespace Barotrauma.Networking
if (c == null || string.IsNullOrEmpty(newName) || !NetIdUtils.IdMoreRecent(nameId, c.NameId)) { return false; }
var timeSinceNameChange = DateTime.Now - c.LastNameChangeTime;
if (timeSinceNameChange < Client.NameChangeCoolDown)
if (timeSinceNameChange < Client.NameChangeCoolDown && newName != c.Name)
{
//only send once per second at most to prevent using this for spamming
if (timeSinceNameChange.TotalSeconds > 1)
{
var coolDownRemaining = Client.NameChangeCoolDown - timeSinceNameChange;
SendDirectChatMessage($"ServerMessage.NameChangeFailedCooldownActive~[seconds]={(int)coolDownRemaining.TotalSeconds}", c);
LastClientListUpdateID++;
}
c.NameId = nameId;
c.RejectedName = newName;
@@ -3558,14 +3578,9 @@ namespace Barotrauma.Networking
serverPeer.Send(msg, client.Connection, DeliveryMethod.Reliable);
}
public void SendTraitorMessage(Client client, string message, Identifier missionIdentifier, TraitorMessageType messageType)
public void SendTraitorMessage(WriteOnlyMessage msg, Client client)
{
if (client == null) { return; }
var msg = new WriteOnlyMessage();
msg.WriteByte((byte)ServerPacketHeader.TRAITOR_MESSAGE);
msg.WriteByte((byte)messageType);
msg.WriteIdentifier(missionIdentifier);
msg.WriteString(message);
if (client == null) { return; };
serverPeer.Send(msg, client.Connection, DeliveryMethod.ReliableOrdered);
}
@@ -240,19 +240,20 @@ namespace Barotrauma
{
Client targetClient = GameMain.Server.ConnectedClients.Find(c => c.Character == inventory.Owner);
Character yoinkerCharacter = yoinker?.Character;
Character thiefCharacter = yoinker?.Character;
Character targetCharacter = inventory.Owner as Character;
if (yoinker == null || item == null || yoinkerCharacter == null || targetCharacter == null || yoinkerCharacter == targetCharacter) { return; }
if (yoinker == null || item == null || thiefCharacter == null || targetCharacter == null || thiefCharacter == targetCharacter) { return; }
if (targetClient == null && (!DangerousItemStealBots || targetCharacter.AIController == null)) { return; }
// Only if the target is alive and they are stunned, unconscious or handcuffed
if (targetCharacter.IsDead || targetCharacter.Removed || !(targetCharacter.Stun > 0) && !targetCharacter.IsUnconscious && !targetCharacter.LockHands) { return; }
if (GameMain.Server.TraitorManager?.Traitors != null)
if (GameMain.Server.TraitorManager != null)
{
if (GameMain.Server.TraitorManager.Traitors.Any(t => t.Character == targetCharacter || t.Character == yoinkerCharacter))
if (GameMain.Server.TraitorManager.IsTraitor(targetCharacter) ||
GameMain.Server.TraitorManager.IsTraitor(thiefCharacter))
{
// Don't penalize traitors
return;
@@ -299,7 +300,7 @@ namespace Barotrauma
}
// Name tag doesn't belong to anyone in particular or we own the ID card
if (name == null || name == yoinkerCharacter.Name) { return; }
if (name == null || name == thiefCharacter.Name) { return; }
}
if (MathUtils.NearlyEqual(DangerousItemStealKarmaDecrease, 0)) { return; }
@@ -329,7 +330,7 @@ namespace Barotrauma
karmaDecrease *= 0.5f;
}
AdjustKarma(yoinkerCharacter, -karmaDecrease, "Stolen dangerous item");
AdjustKarma(thiefCharacter, -karmaDecrease, "Stolen dangerous item");
}
public void OnCharacterHealthChanged(Character target, Character attacker, float damage, float stun, IEnumerable<Affliction> appliedAfflictions = null)
@@ -341,27 +342,23 @@ namespace Barotrauma
if (target.IsDead || target.Removed) { return; }
bool isEnemy = target.AIController is EnemyAIController || target.TeamID != attacker.TeamID;
if (GameMain.Server.TraitorManager?.Traitors != null)
if (GameMain.Server.TraitorManager != null)
{
if (GameMain.Server.TraitorManager.Traitors.Any(t => t.Character == target))
if (GameMain.Server.TraitorManager.IsTraitor(target))
{
//traitors always count as enemies
isEnemy = true;
}
if (GameMain.Server.TraitorManager.Traitors.Any(t =>
t.Character == attacker &&
t.CurrentObjective != null &&
t.CurrentObjective.IsEnemy(target)))
if (GameMain.Server.TraitorManager.IsTraitor(attacker))
{
//target counts as an enemy to the traitor
//others count as an enemies to the traitor
isEnemy = true;
}
}
bool targetIsHusk = target.CharacterHealth?.GetAffliction<AfflictionHusk>(AfflictionPrefab.HuskInfectionType)?.State == AfflictionHusk.InfectionState.Active;
bool attackerIsHusk = attacker.CharacterHealth?.GetAffliction<AfflictionHusk>(AfflictionPrefab.HuskInfectionType)?.State == AfflictionHusk.InfectionState.Active;
static bool IsHusk(Character c) => c.IsHusk || c.IsHuskInfected;
//huskified characters count as enemies to healthy characters and vice versa
if (targetIsHusk != attackerIsHusk) { isEnemy = true; }
if (IsHusk(attacker) != IsHusk(target)) { isEnemy = true; }
if (appliedAfflictions != null)
{
@@ -478,14 +475,11 @@ namespace Barotrauma
if (damageAmount > 0)
{
if (StructureDamageKarmaDecrease <= 0.0f) { return; }
if (GameMain.Server.TraitorManager?.Traitors != null)
if (GameMain.Server.TraitorManager != null)
{
if (GameMain.Server.TraitorManager.Traitors.Any(t =>
t.Character == attacker &&
t.CurrentObjective != null &&
t.CurrentObjective.IsAllowedToDamage(structure)))
if (GameMain.Server.TraitorManager.IsTraitor(attacker))
{
//traitor tasked to flood the sub -> damaging structures is ok
//traitors are allowed to damage structures
return;
}
}
@@ -580,7 +574,7 @@ namespace Barotrauma
public void OnItemContained(Item containedItem, Item container, Character character)
{
if (containedItem == null || container == null || character == null || character.IsTraitor) { return; }
if (container.Prefab.Identifier == "weldingtool" && containedItem.HasTag("oxygensource"))
if (container.Prefab.Identifier == Tags.WeldingFuel && containedItem.HasTag(Tags.OxygenSource))
{
var client = GameMain.Server.ConnectedClients.Find(c => c.Character == character);
if (client == null) { return; }
@@ -614,7 +608,7 @@ namespace Barotrauma
if (amount < 0.0f)
{
float? herpesStrength = client.Character?.CharacterHealth.GetAfflictionStrength(AfflictionPrefab.SpaceHerpesType);
float? herpesStrength = client.Character?.CharacterHealth.GetAfflictionStrengthByType(AfflictionPrefab.SpaceHerpesType);
var clientMemory = GetClientMemory(client);
clientMemory.KarmaDecreasesInPastMinute.RemoveAll(ta => ta.Time + 60.0f < Timing.TotalTime);
float aggregate = clientMemory.KarmaDecreasesInPastMinute.Select(ta => ta.Amount).DefaultIfEmpty().Aggregate((a, b) => a + b);
@@ -27,7 +27,8 @@ namespace Barotrauma.Networking
AutoExpandMTU = false,
MaximumConnections = NetConfig.MaxPlayers * 2,
EnableUPnP = serverSettings.EnableUPnP,
Port = serverSettings.Port
Port = serverSettings.Port,
DualStack = GameSettings.CurrentConfig.UseDualModeSockets
};
netPeerConfiguration.DisableMessageType(
@@ -433,9 +433,9 @@ namespace Barotrauma.Networking
}
//tell the respawning client they're no longer a traitor
if (GameMain.Server.TraitorManager?.Traitors != null && clients[i].Character != null)
if (GameMain.Server.TraitorManager != null && clients[i].Character != null)
{
if (GameMain.Server.TraitorManager.Traitors.Any(t => t.Character == clients[i].Character))
if (GameMain.Server.TraitorManager.IsTraitor(clients[i].Character))
{
GameMain.Server.SendDirectChatMessage(TextManager.FormatServerMessage("TraitorRespawnMessage"), clients[i], ChatMessageType.ServerMessageBox);
}
@@ -537,18 +537,7 @@ namespace Barotrauma.Networking
}
//add the ID card tags they should've gotten when spawning in the shuttle
foreach (Item item in character.Inventory.AllItems.Distinct())
{
if (item.GetComponent<IdCard>() == null) { continue; }
foreach (string s in shuttleSpawnPoints[i].IdCardTags)
{
item.AddTag(s);
}
if (!string.IsNullOrWhiteSpace(shuttleSpawnPoints[i].IdCardDesc))
{
item.Description = shuttleSpawnPoints[i].IdCardDesc;
}
}
character.GiveIdCardTags(shuttleSpawnPoints[i], requireSpawnPointTagsNotGiven: false, createNetworkEvent: true);
}
}
@@ -559,7 +548,7 @@ namespace Barotrauma.Networking
{
var skillPrefab = characterInfo.Job.Prefab.Skills.Find(s => skill.Identifier == s.Identifier);
if (skillPrefab == null || skill.Level < skillPrefab.LevelRange.End) { continue; }
skill.Level = MathHelper.Lerp(skill.Level, skillPrefab.LevelRange.End, SkillReductionOnDeath);
skill.Level = MathHelper.Lerp(skill.Level, skillPrefab.LevelRange.End, SkillLossPercentageOnDeath / 100.0f);
}
}
@@ -215,11 +215,15 @@ namespace Barotrauma.Networking
int orBits = incMsg.ReadRangedInteger(0, (int)Barotrauma.MissionType.All) & (int)Barotrauma.MissionType.All;
int andBits = incMsg.ReadRangedInteger(0, (int)Barotrauma.MissionType.All) & (int)Barotrauma.MissionType.All;
GameMain.NetLobbyScreen.MissionType = (MissionType)(((int)GameMain.NetLobbyScreen.MissionType | orBits) & andBits);
int traitorSetting = (int)TraitorsEnabled + incMsg.ReadByte() - 1;
if (traitorSetting < 0) { traitorSetting = 2; }
if (traitorSetting > 2) { traitorSetting = 0; }
TraitorsEnabled = (YesNoMaybe)traitorSetting;
bool changedTraitorProbability = incMsg.ReadBoolean();
float traitorProbability = incMsg.ReadSingle();
if (changedTraitorProbability)
{
TraitorProbability = traitorProbability;
}
//the byte indicates the direction we're changing the value, subtract one to get negative values from a byte
TraitorDangerLevel = TraitorDangerLevel + incMsg.ReadByte() - 1;
int botCount = BotCount + incMsg.ReadByte() - 1;
if (botCount < 0) { botCount = MaxBotCount; }
@@ -347,7 +351,7 @@ namespace Barotrauma.Networking
selectedLevelDifficulty = doc.Root.GetAttributeFloat("LevelDifficulty", 20.0f);
GameMain.NetLobbyScreen.SetLevelDifficulty(selectedLevelDifficulty);
GameMain.NetLobbyScreen.SetTraitorsEnabled(traitorsEnabled);
GameMain.NetLobbyScreen.SetTraitorProbability(traitorProbability);
HiddenSubs.UnionWith(doc.Root.GetAttributeStringArray("HiddenSubs", Array.Empty<string>()));
if (HiddenSubs.Any())
@@ -337,6 +337,20 @@ namespace Barotrauma
sender.SetVote(voteType, (int)inc.ReadByte());
}
break;
case VoteType.Traitor:
int clientId = inc.ReadInt32();
if (sender.InGame && sender.Character != null)
{
var client = GameMain.Server.ConnectedClients.FirstOrDefault(c => c.SessionId == clientId);
sender.SetVote(voteType, client);
if (client?.Character != null)
{
GameMain.Server.SendChatMessage(
TextManager.GetWithVariable("traitor.blamebutton.dialog", "[name]", client.Character.DisplayName).Value,
ChatMessageType.Radio, senderClient: sender, senderCharacter: sender.Character);
}
}
break;
}
inc.ReadPadBits();