(bf212a41f) v0.9.2.0 pre-release test version
This commit is contained in:
@@ -83,8 +83,9 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (similarity + c.ChatSpamSpeed > 5.0f && !isOwner)
|
||||
{
|
||||
c.ChatSpamCount++;
|
||||
GameMain.Server.KarmaManager.OnSpamFilterTriggered(c);
|
||||
|
||||
c.ChatSpamCount++;
|
||||
if (c.ChatSpamCount > 3)
|
||||
{
|
||||
//kick for spamming too much
|
||||
|
||||
@@ -65,20 +65,19 @@ namespace Barotrauma.Networking
|
||||
|
||||
public bool SpectateOnly;
|
||||
|
||||
private float karma = 1.0f;
|
||||
private float karma = 100.0f;
|
||||
public float Karma
|
||||
{
|
||||
get
|
||||
{
|
||||
if (GameMain.Server == null) return 1.0f;
|
||||
if (!GameMain.Server.ServerSettings.KarmaEnabled) return 1.0f;
|
||||
if (GameMain.Server == null || !GameMain.Server.ServerSettings.KarmaEnabled) { return 100.0f; }
|
||||
if (HasPermission(ClientPermissions.KarmaImmunity)) { return 100.0f; }
|
||||
return karma;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (GameMain.Server == null) return;
|
||||
if (!GameMain.Server.ServerSettings.KarmaEnabled) return;
|
||||
karma = Math.Min(Math.Max(value, 0.0f), 1.0f);
|
||||
if (GameMain.Server == null || !GameMain.Server.ServerSettings.KarmaEnabled) { return; }
|
||||
karma = Math.Min(Math.Max(value, 0.0f), 100.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
get { return entityEventManager; }
|
||||
}
|
||||
|
||||
|
||||
public TimeSpan UpdateInterval
|
||||
{
|
||||
get { return updateInterval; }
|
||||
@@ -109,7 +109,6 @@ namespace Barotrauma.Networking
|
||||
LastClientListUpdateID = 0;
|
||||
|
||||
NetPeerConfiguration = new NetPeerConfiguration("barotrauma");
|
||||
|
||||
NetPeerConfiguration.Port = port;
|
||||
Port = port;
|
||||
QueryPort = queryPort;
|
||||
@@ -119,12 +118,12 @@ namespace Barotrauma.Networking
|
||||
NetPeerConfiguration.EnableUPnP = true;
|
||||
}
|
||||
|
||||
serverSettings = new ServerSettings(name, port, queryPort, maxPlayers, isPublic, attemptUPnP);
|
||||
serverSettings = new ServerSettings(this, name, port, queryPort, maxPlayers, isPublic, attemptUPnP);
|
||||
if (!string.IsNullOrEmpty(password))
|
||||
{
|
||||
serverSettings.SetPassword(password);
|
||||
}
|
||||
|
||||
|
||||
NetPeerConfiguration.MaximumConnections = maxPlayers * 2; //double the lidgren connections for unauthenticated players
|
||||
|
||||
NetPeerConfiguration.DisableMessageType(NetIncomingMessageType.DebugMessage |
|
||||
@@ -353,6 +352,7 @@ namespace Barotrauma.Networking
|
||||
unauthenticatedClients.RemoveAll(uc => uc.AuthTimer <= 0.0f);
|
||||
|
||||
fileSender.Update(deltaTime);
|
||||
KarmaManager.UpdateClients(ConnectedClients, deltaTime);
|
||||
|
||||
if (serverSettings.VoiceChatEnabled)
|
||||
{
|
||||
@@ -361,7 +361,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (gameStarted)
|
||||
{
|
||||
if (respawnManager != null) respawnManager.Update(deltaTime);
|
||||
if (respawnManager != null) { respawnManager.Update(deltaTime); }
|
||||
|
||||
entityEventManager.Update(connectedClients);
|
||||
|
||||
@@ -415,25 +415,32 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
if (isCrewDead && respawnManager == null)
|
||||
float endRoundDelay = 1.0f;
|
||||
if (serverSettings.AutoRestart && isCrewDead)
|
||||
{
|
||||
endRoundDelay = 5.0f;
|
||||
endRoundTimer += deltaTime;
|
||||
}
|
||||
else if (serverSettings.EndRoundAtLevelEnd && subAtLevelEnd)
|
||||
{
|
||||
endRoundDelay = 5.0f;
|
||||
endRoundTimer += deltaTime;
|
||||
}
|
||||
else if (isCrewDead && respawnManager == null)
|
||||
{
|
||||
if (endRoundTimer <= 0.0f)
|
||||
{
|
||||
SendChatMessage(TextManager.GetWithVariable("CrewDeadNoRespawns", "[time]", "60"), ChatMessageType.Server);
|
||||
}
|
||||
endRoundDelay = 60.0f;
|
||||
endRoundTimer += deltaTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
endRoundTimer = 0.0f;
|
||||
}
|
||||
|
||||
//restart if all characters are dead or submarine is at the end of the level
|
||||
if ((serverSettings.AutoRestart && isCrewDead)
|
||||
||
|
||||
(serverSettings.EndRoundAtLevelEnd && subAtLevelEnd)
|
||||
||
|
||||
(isCrewDead && respawnManager == null && endRoundTimer >= 60.0f))
|
||||
|
||||
if (endRoundTimer >= endRoundDelay)
|
||||
{
|
||||
if (serverSettings.AutoRestart && isCrewDead)
|
||||
{
|
||||
@@ -1029,6 +1036,9 @@ namespace Barotrauma.Networking
|
||||
case ClientNetObject.VOTE:
|
||||
serverSettings.Voting.ServerRead(inc, c);
|
||||
break;
|
||||
case ClientNetObject.SPECTATING_POS:
|
||||
c.SpectatePos = new Vector2(inc.ReadFloat(), inc.ReadFloat());
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
@@ -1346,11 +1356,20 @@ namespace Barotrauma.Networking
|
||||
foreach (Character character in Character.CharacterList)
|
||||
{
|
||||
if (!character.Enabled) continue;
|
||||
if (c.Character != null &&
|
||||
Vector2.DistanceSquared(character.WorldPosition, c.Character.WorldPosition) >=
|
||||
NetConfig.DisableCharacterDistSqr)
|
||||
|
||||
if (c.SpectatePos == null)
|
||||
{
|
||||
continue;
|
||||
if (c.Character != null && Vector2.DistanceSquared(character.WorldPosition, c.Character.WorldPosition) >= NetConfig.DisableCharacterDistSqr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Vector2.DistanceSquared(character.WorldPosition, c.SpectatePos.Value) >= NetConfig.DisableCharacterDistSqr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
float updateInterval = character.GetPositionUpdateInterval(c);
|
||||
@@ -2005,8 +2024,16 @@ namespace Barotrauma.Networking
|
||||
|
||||
public void EndGame()
|
||||
{
|
||||
if (!gameStarted) return;
|
||||
Log("Ending the round...", ServerLog.MessageType.ServerMessage);
|
||||
if (!gameStarted) { return; }
|
||||
if (GameSettings.VerboseLogging)
|
||||
{
|
||||
Log("Ending the round...\n" + Environment.StackTrace, ServerLog.MessageType.ServerMessage);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("Ending the round...", ServerLog.MessageType.ServerMessage);
|
||||
}
|
||||
|
||||
string endMessage = "The round has ended." + '\n';
|
||||
|
||||
@@ -2068,31 +2095,14 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
CoroutineManager.StartCoroutine(EndCinematic(), "EndCinematic");
|
||||
|
||||
GameMain.NetLobbyScreen.RandomizeSettings();
|
||||
}
|
||||
|
||||
public IEnumerable<object> EndCinematic()
|
||||
{
|
||||
float endPreviewLength = 10.0f;
|
||||
|
||||
var cinematic = new RoundEndCinematic(Submarine.MainSub, GameMain.GameScreen.Cam, endPreviewLength);
|
||||
|
||||
do
|
||||
{
|
||||
yield return CoroutineStatus.Running;
|
||||
} while (cinematic.Running);
|
||||
|
||||
Submarine.Unload();
|
||||
entityEventManager.Clear();
|
||||
|
||||
GameMain.NetLobbyScreen.Select();
|
||||
Log("Round ended.", ServerLog.MessageType.ServerMessage);
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
GameMain.NetLobbyScreen.RandomizeSettings();
|
||||
}
|
||||
|
||||
|
||||
public override void AddChatMessage(ChatMessage message)
|
||||
{
|
||||
if (string.IsNullOrEmpty(message.Text)) { return; }
|
||||
@@ -2257,6 +2267,7 @@ namespace Barotrauma.Networking
|
||||
previousPlayers.Add(previousPlayer);
|
||||
}
|
||||
previousPlayer.Name = client.Name;
|
||||
previousPlayer.Karma = client.Karma;
|
||||
previousPlayer.KickVoters.Clear();
|
||||
foreach (Client c in connectedClients)
|
||||
{
|
||||
@@ -2267,6 +2278,8 @@ namespace Barotrauma.Networking
|
||||
client.Dispose();
|
||||
connectedClients.Remove(client);
|
||||
|
||||
KarmaManager.OnClientDisconnected(client);
|
||||
|
||||
UpdateVoteStatus();
|
||||
|
||||
SendChatMessage(msg, ChatMessageType.Server);
|
||||
@@ -3077,6 +3090,7 @@ namespace Barotrauma.Networking
|
||||
public string Name;
|
||||
public string IP;
|
||||
public UInt64 SteamID;
|
||||
public float Karma;
|
||||
public readonly List<Client> KickVoters = new List<Client>();
|
||||
|
||||
public PreviousPlayer(Client c)
|
||||
|
||||
@@ -472,9 +472,10 @@ namespace Barotrauma.Networking
|
||||
unauthClient = null;
|
||||
ConnectedClients.Add(newClient);
|
||||
|
||||
var previousPlayer = previousPlayers.Find(p => p.MatchesClient(newClient));
|
||||
var previousPlayer = previousPlayers.Find(p => p.MatchesClient(newClient));
|
||||
if (previousPlayer != null)
|
||||
{
|
||||
newClient.Karma = previousPlayer.Karma;
|
||||
foreach (Client c in previousPlayer.KickVoters)
|
||||
{
|
||||
if (!connectedClients.Contains(c)) { continue; }
|
||||
|
||||
@@ -0,0 +1,337 @@
|
||||
using Barotrauma.Items.Components;
|
||||
using Barotrauma.Networking;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class KarmaManager : ISerializableEntity
|
||||
{
|
||||
private class ClientMemory
|
||||
{
|
||||
public List<Pair<Wire, float>> WireDisconnectTime = new List<Pair<Wire, float>>();
|
||||
|
||||
//the client's karma value when they were last sent a notification about it (e.g. "your karma is very low")
|
||||
public float PreviousNotifiedKarma;
|
||||
|
||||
public float StructureDamageAccumulator;
|
||||
|
||||
private float structureDamagePerSecond;
|
||||
public float StructureDamagePerSecond
|
||||
{
|
||||
get { return Math.Max(StructureDamageAccumulator, structureDamagePerSecond); }
|
||||
set { structureDamagePerSecond = value; }
|
||||
}
|
||||
}
|
||||
|
||||
public bool TestMode = false;
|
||||
|
||||
private readonly Dictionary<Client, ClientMemory> clientMemories = new Dictionary<Client, ClientMemory>();
|
||||
private readonly List<Client> bannedClients = new List<Client>();
|
||||
|
||||
private DateTime perSecondUpdate;
|
||||
|
||||
private double KarmaNotificationTime;
|
||||
|
||||
public void UpdateClients(IEnumerable<Client> clients, float deltaTime)
|
||||
{
|
||||
if (!GameMain.Server.GameStarted) { return; }
|
||||
|
||||
bannedClients.Clear();
|
||||
foreach (Client client in clients)
|
||||
{
|
||||
var clientMemory = GetClientMemory(client);
|
||||
UpdateClient(client, deltaTime);
|
||||
|
||||
if (perSecondUpdate < DateTime.Now)
|
||||
{
|
||||
clientMemory.StructureDamagePerSecond = clientMemory.StructureDamageAccumulator;
|
||||
clientMemory.StructureDamageAccumulator = 0.0f;
|
||||
}
|
||||
}
|
||||
if (perSecondUpdate < DateTime.Now)
|
||||
{
|
||||
perSecondUpdate = DateTime.Now + new TimeSpan(0, 0, 1);
|
||||
}
|
||||
|
||||
if (TestMode || Timing.TotalTime > KarmaNotificationTime)
|
||||
{
|
||||
foreach (Client client in clients)
|
||||
{
|
||||
SendKarmaNotifications(client);
|
||||
}
|
||||
KarmaNotificationTime = Timing.TotalTime + KarmaNotificationInterval;
|
||||
}
|
||||
|
||||
foreach (Client bannedClient in bannedClients)
|
||||
{
|
||||
GameMain.Server.BanClient(bannedClient, $"KarmaBanned~[banthreshold]={(int)KickBanThreshold}", duration: TimeSpan.FromSeconds(GameMain.Server.ServerSettings.AutoBanTime));
|
||||
}
|
||||
}
|
||||
|
||||
private void SendKarmaNotifications(Client client, string debugKarmaChangeReason = "")
|
||||
{
|
||||
var clientMemory = GetClientMemory(client);
|
||||
float karmaChange = client.Karma - clientMemory.PreviousNotifiedKarma;
|
||||
if (Math.Abs(karmaChange) > KarmaNotificationInterval || (TestMode && Math.Abs(karmaChange) > 2.0f))
|
||||
{
|
||||
if (TestMode)
|
||||
{
|
||||
string msg =
|
||||
karmaChange < 0 ? $"You karma has decreased to {client.Karma}" : $"You karma has increased to {client.Karma}";
|
||||
if (!string.IsNullOrEmpty(debugKarmaChangeReason))
|
||||
{
|
||||
msg += $". Reason: {debugKarmaChangeReason}";
|
||||
}
|
||||
GameMain.Server.SendDirectChatMessage(msg, client);
|
||||
}
|
||||
else if (Math.Abs(KickBanThreshold - client.Karma) < KarmaNotificationInterval)
|
||||
{
|
||||
GameMain.Server.SendDirectChatMessage(TextManager.Get("KarmaBanWarning"), client);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMain.Server.SendDirectChatMessage(TextManager.Get(karmaChange < 0 ? "KarmaDecreasedUnknownAmount" : "KarmaIncreasedUnknownAmount"), client);
|
||||
}
|
||||
clientMemory.PreviousNotifiedKarma = client.Karma;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateClient(Client client, float deltaTime)
|
||||
{
|
||||
if (client.Karma > KarmaDecayThreshold)
|
||||
{
|
||||
client.Karma -= KarmaDecay * deltaTime;
|
||||
}
|
||||
else if (client.Karma < KarmaIncreaseThreshold)
|
||||
{
|
||||
client.Karma += KarmaIncrease * deltaTime;
|
||||
}
|
||||
|
||||
if (client.Character != null && !client.Character.Removed)
|
||||
{
|
||||
//increase the strength of the herpes affliction in steps instead of linearly
|
||||
//otherwise clients could determine their exact karma value from the strength
|
||||
float herpesStrength = 0.0f;
|
||||
if (client.Karma < 20)
|
||||
herpesStrength = 100.0f;
|
||||
else if (client.Karma < 30)
|
||||
herpesStrength = 60.0f;
|
||||
else if (client.Karma < 40.0f)
|
||||
herpesStrength = 30.0f;
|
||||
|
||||
var existingAffliction = client.Character.CharacterHealth.GetAffliction<AfflictionSpaceHerpes>("spaceherpes");
|
||||
if (existingAffliction == null && herpesStrength > 0.0f)
|
||||
{
|
||||
client.Character.CharacterHealth.ApplyAffliction(null, new Affliction(herpesAffliction, herpesStrength));
|
||||
}
|
||||
else if (existingAffliction != null)
|
||||
{
|
||||
existingAffliction.Strength = herpesStrength;
|
||||
}
|
||||
|
||||
//check if the client has disconnected an excessive number of wires
|
||||
var clientMemory = GetClientMemory(client);
|
||||
if (clientMemory.WireDisconnectTime.Count > (int)AllowedWireDisconnectionsPerMinute)
|
||||
{
|
||||
clientMemory.WireDisconnectTime.RemoveRange(0, clientMemory.WireDisconnectTime.Count - (int)AllowedWireDisconnectionsPerMinute);
|
||||
if (clientMemory.WireDisconnectTime.All(w => Timing.TotalTime - w.Second < 60.0f))
|
||||
{
|
||||
float karmaDecrease = -WireDisconnectionKarmaDecrease;
|
||||
//engineers don't lose as much karma for removing lots of wires
|
||||
if (client.Character.Info?.Job.Prefab.Identifier == "engineer") { karmaDecrease *= 0.5f; }
|
||||
AdjustKarma(client.Character, karmaDecrease, "Disconnected excessive number of wires");
|
||||
}
|
||||
}
|
||||
|
||||
if (client.Character?.Info?.Job.Prefab.Identifier == "captain" && client.Character.SelectedConstruction != null)
|
||||
{
|
||||
if (client.Character.SelectedConstruction.GetComponent<Steering>() != null)
|
||||
{
|
||||
AdjustKarma(client.Character, SteerSubKarmaIncrease * deltaTime, "Steering the sub");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (client.Karma < KickBanThreshold && client.Connection != GameMain.Server.OwnerConnection)
|
||||
{
|
||||
if (TestMode)
|
||||
{
|
||||
client.Karma = 50.0f;
|
||||
GameMain.Server.SendDirectChatMessage("BANNED! (not really because karma test mode is enabled)", client);
|
||||
}
|
||||
else
|
||||
{
|
||||
bannedClients.Add(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnClientDisconnected(Client client)
|
||||
{
|
||||
clientMemories.Remove(client);
|
||||
}
|
||||
|
||||
public void OnCharacterHealthChanged(Character target, Character attacker, float damage, IEnumerable<Affliction> appliedAfflictions = null)
|
||||
{
|
||||
if (target == null || attacker == null) { return; }
|
||||
if (target == attacker) { return; }
|
||||
|
||||
//damaging dead characters doesn't affect karma
|
||||
if (target.IsDead || target.Removed) { return; }
|
||||
|
||||
bool isEnemy = target.AIController is EnemyAIController || target.TeamID != attacker.TeamID;
|
||||
if (GameMain.Server.TraitorManager != null)
|
||||
{
|
||||
if (GameMain.Server.TraitorManager.TraitorList.Any(t => t.Character == target))
|
||||
{
|
||||
//traitors always count as enemies
|
||||
isEnemy = true;
|
||||
}
|
||||
if (GameMain.Server.TraitorManager.TraitorList.Any(t => t.Character == attacker && t.TargetCharacter == target))
|
||||
{
|
||||
//target counts as an enemy to the traitor
|
||||
isEnemy = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (appliedAfflictions != null)
|
||||
{
|
||||
foreach (Affliction affliction in appliedAfflictions)
|
||||
{
|
||||
if (MathUtils.NearlyEqual(affliction.Prefab.KarmaChangeOnApplied, 0.0f)) { continue; }
|
||||
damage -= affliction.Prefab.KarmaChangeOnApplied * affliction.Strength;
|
||||
}
|
||||
}
|
||||
|
||||
if (target.AIController is EnemyAIController || target.TeamID != attacker.TeamID)
|
||||
{
|
||||
if (damage > 0)
|
||||
{
|
||||
float karmaIncrease = damage * DamageEnemyKarmaIncrease;
|
||||
if (attacker?.Info?.Job.Prefab.Identifier == "securityofficer") { karmaIncrease *= 2.0f; }
|
||||
AdjustKarma(attacker, karmaIncrease, "Damaged enemy");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (damage > 0)
|
||||
{
|
||||
AdjustKarma(attacker, -damage * DamageFriendlyKarmaDecrease, "Damaged friendly");
|
||||
}
|
||||
else
|
||||
{
|
||||
float karmaIncrease = -damage * HealFriendlyKarmaIncrease;
|
||||
if (attacker?.Info?.Job.Prefab.Identifier == "medicaldoctor") { karmaIncrease *= 2.0f; }
|
||||
AdjustKarma(attacker, karmaIncrease, "Healed friendly");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void OnStructureHealthChanged(Structure structure, Character attacker, float damageAmount)
|
||||
{
|
||||
if (attacker == null) { return; }
|
||||
//damaging/repairing ruin structures or enemy subs doesn't affect karma
|
||||
if (structure.Submarine == null || structure.Submarine.TeamID != attacker.TeamID)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (damageAmount > 0)
|
||||
{
|
||||
if (StructureDamageKarmaDecrease <= 0.0f) { return; }
|
||||
Client client = GameMain.Server.ConnectedClients.Find(c => c.Character == attacker);
|
||||
if (client != null)
|
||||
{
|
||||
//cap the damage so the karma can't decrease by more than MaxStructureDamageKarmaDecreasePerSecond per second
|
||||
var clientMemory = GetClientMemory(client);
|
||||
clientMemory.StructureDamageAccumulator += damageAmount;
|
||||
if (clientMemory.StructureDamagePerSecond + damageAmount >= MaxStructureDamageKarmaDecreasePerSecond / StructureDamageKarmaDecrease)
|
||||
{
|
||||
damageAmount -= (MaxStructureDamageKarmaDecreasePerSecond / StructureDamageKarmaDecrease) - clientMemory.StructureDamagePerSecond;
|
||||
if (damageAmount <= 0.0f) { return; }
|
||||
}
|
||||
}
|
||||
AdjustKarma(attacker, -damageAmount * StructureDamageKarmaDecrease, "Damaged structures");
|
||||
}
|
||||
else
|
||||
{
|
||||
float karmaIncrease = -damageAmount * StructureRepairKarmaIncrease;
|
||||
//mechanics get twice as much karma for repairing walls
|
||||
if (attacker.Info?.Job.Prefab.Identifier == "mechanic") { karmaIncrease *= 2.0f; }
|
||||
AdjustKarma(attacker, karmaIncrease, "Repaired structures");
|
||||
}
|
||||
}
|
||||
|
||||
public void OnItemRepaired(Character character, Repairable repairable, float repairAmount)
|
||||
{
|
||||
float karmaIncrease = repairAmount * ItemRepairKarmaIncrease;
|
||||
if (repairable.HasRequiredSkills(character)) { karmaIncrease *= 2.0f; }
|
||||
AdjustKarma(character, karmaIncrease, "Repaired item");
|
||||
}
|
||||
|
||||
public void OnReactorOverHeating(Character character, float deltaTime)
|
||||
{
|
||||
AdjustKarma(character, -ReactorOverheatKarmaDecrease * deltaTime, "Caused reactor to overheat");
|
||||
}
|
||||
|
||||
public void OnReactorMeltdown(Character character)
|
||||
{
|
||||
AdjustKarma(character, -ReactorMeltdownKarmaDecrease, "Caused a reactor meltdown");
|
||||
}
|
||||
|
||||
public void OnExtinguishingFire(Character character, float deltaTime)
|
||||
{
|
||||
AdjustKarma(character, ExtinguishFireKarmaIncrease * deltaTime, "Extinguished a fire");
|
||||
}
|
||||
|
||||
public void OnWireDisconnected(Character character, Wire wire)
|
||||
{
|
||||
if (character == null || wire == null) { return; }
|
||||
Client client = GameMain.Server.ConnectedClients.Find(c => c.Character == character);
|
||||
if (client == null) { return; }
|
||||
|
||||
if (!clientMemories.ContainsKey(client)) { clientMemories[client] = new ClientMemory(); }
|
||||
|
||||
clientMemories[client].WireDisconnectTime.RemoveAll(w => w.First == wire);
|
||||
clientMemories[client].WireDisconnectTime.Add(new Pair<Wire, float>(wire, (float)Timing.TotalTime));
|
||||
}
|
||||
|
||||
private ClientMemory GetClientMemory(Client client)
|
||||
{
|
||||
if (!clientMemories.ContainsKey(client))
|
||||
{
|
||||
clientMemories[client] = new ClientMemory()
|
||||
{
|
||||
PreviousNotifiedKarma = client.Karma
|
||||
};
|
||||
}
|
||||
return clientMemories[client];
|
||||
}
|
||||
|
||||
public void OnSpamFilterTriggered(Client client)
|
||||
{
|
||||
if (client != null)
|
||||
{
|
||||
client.Karma -= SpamFilterKarmaDecrease;
|
||||
SendKarmaNotifications(client, "Triggered the spam filter");
|
||||
}
|
||||
}
|
||||
|
||||
private void AdjustKarma(Character target, float amount, string debugKarmaChangeReason = "")
|
||||
{
|
||||
if (target == null) { return; }
|
||||
|
||||
Client client = GameMain.Server.ConnectedClients.Find(c => c.Character == target);
|
||||
if (client == null) { return; }
|
||||
|
||||
client.Karma += amount;
|
||||
if (TestMode)
|
||||
{
|
||||
SendKarmaNotifications(client, debugKarmaChangeReason);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Barotrauma.Items.Components;
|
||||
using Lidgren.Network;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -53,36 +54,34 @@ namespace Barotrauma.Networking
|
||||
return botsToRespawn;
|
||||
}
|
||||
|
||||
partial void UpdateWaiting(float deltaTime)
|
||||
private bool RespawnPending()
|
||||
{
|
||||
int characterToRespawnCount = GetClientsToRespawn().Count;
|
||||
int totalCharacterCount = GameMain.Server.ConnectedClients.Count;
|
||||
/*if (server.Character != null)
|
||||
{
|
||||
totalCharacterCount++;
|
||||
if (server.Character.IsDead) characterToRespawnCount++;
|
||||
}*/
|
||||
bool startCountdown = (float)characterToRespawnCount >= Math.Max((float)totalCharacterCount * GameMain.Server.ServerSettings.MinRespawnRatio, 1.0f);
|
||||
return (float)characterToRespawnCount >= Math.Max((float)totalCharacterCount * GameMain.Server.ServerSettings.MinRespawnRatio, 1.0f);
|
||||
}
|
||||
|
||||
if (startCountdown != CountdownStarted)
|
||||
partial void UpdateWaiting(float deltaTime)
|
||||
{
|
||||
bool respawnPending = RespawnPending();
|
||||
if (respawnPending != RespawnCountdownStarted)
|
||||
{
|
||||
CountdownStarted = startCountdown;
|
||||
RespawnCountdownStarted = respawnPending;
|
||||
RespawnTime = DateTime.Now + new TimeSpan(0,0,0,0, (int)(GameMain.Server.ServerSettings.RespawnInterval * 1000.0f));
|
||||
GameMain.Server.CreateEntityEvent(this);
|
||||
}
|
||||
|
||||
if (!CountdownStarted) return;
|
||||
if (!RespawnCountdownStarted) { return; }
|
||||
|
||||
respawnTimer -= deltaTime;
|
||||
if (respawnTimer <= 0.0f)
|
||||
if (DateTime.Now > RespawnTime)
|
||||
{
|
||||
respawnTimer = GameMain.Server.ServerSettings.RespawnInterval;
|
||||
|
||||
DispatchShuttle();
|
||||
RespawnCountdownStarted = false;
|
||||
}
|
||||
|
||||
if (respawnShuttle == null) return;
|
||||
if (RespawnShuttle == null) { return; }
|
||||
|
||||
respawnShuttle.Velocity = Vector2.Zero;
|
||||
RespawnShuttle.Velocity = Vector2.Zero;
|
||||
|
||||
if (shuttleSteering != null)
|
||||
{
|
||||
@@ -93,9 +92,9 @@ namespace Barotrauma.Networking
|
||||
|
||||
partial void DispatchShuttle()
|
||||
{
|
||||
if (respawnShuttle != null)
|
||||
if (RespawnShuttle != null)
|
||||
{
|
||||
state = State.Transporting;
|
||||
CurrentState = State.Transporting;
|
||||
GameMain.Server.CreateEntityEvent(this);
|
||||
|
||||
ResetShuttle();
|
||||
@@ -110,11 +109,27 @@ namespace Barotrauma.Networking
|
||||
RespawnCharacters();
|
||||
|
||||
CoroutineManager.StopCoroutines("forcepos");
|
||||
CoroutineManager.StartCoroutine(ForceShuttleToPos(Level.Loaded.StartPosition - Vector2.UnitY * Level.ShaftHeight, 100.0f), "forcepos");
|
||||
Vector2 spawnPos = FindSpawnPos();
|
||||
if (spawnPos.Y > Level.Loaded.Size.Y)
|
||||
{
|
||||
CoroutineManager.StartCoroutine(ForceShuttleToPos(Level.Loaded.StartPosition - Vector2.UnitY * Level.ShaftHeight, 100.0f), "forcepos");
|
||||
}
|
||||
else
|
||||
{
|
||||
RespawnShuttle.SetPosition(spawnPos);
|
||||
RespawnShuttle.Velocity = Vector2.Zero;
|
||||
if (shuttleSteering != null)
|
||||
{
|
||||
shuttleSteering.AutoPilot = true;
|
||||
shuttleSteering.MaintainPos = true;
|
||||
shuttleSteering.PosToMaintain = RespawnShuttle.WorldPosition;
|
||||
shuttleSteering.UnsentChanges = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
state = State.Waiting;
|
||||
CurrentState = State.Waiting;
|
||||
GameServer.Log("Respawning everyone in main sub.", ServerLog.MessageType.Spawning);
|
||||
GameMain.Server.CreateEntityEvent(this);
|
||||
|
||||
@@ -129,18 +144,18 @@ namespace Barotrauma.Networking
|
||||
if (door.IsOpen) door.TrySetState(false, false, true);
|
||||
}
|
||||
|
||||
var shuttleGaps = Gap.GapList.FindAll(g => g.Submarine == respawnShuttle && g.ConnectedWall != null);
|
||||
var shuttleGaps = Gap.GapList.FindAll(g => g.Submarine == RespawnShuttle && g.ConnectedWall != null);
|
||||
shuttleGaps.ForEach(g => Spawner.AddToRemoveQueue(g));
|
||||
|
||||
var dockingPorts = Item.ItemList.FindAll(i => i.Submarine == respawnShuttle && i.GetComponent<DockingPort>() != null);
|
||||
var dockingPorts = Item.ItemList.FindAll(i => i.Submarine == RespawnShuttle && i.GetComponent<DockingPort>() != null);
|
||||
dockingPorts.ForEach(d => d.GetComponent<DockingPort>().Undock());
|
||||
|
||||
//shuttle has returned if the path has been traversed or the shuttle is close enough to the exit
|
||||
if (!CoroutineManager.IsCoroutineRunning("forcepos"))
|
||||
{
|
||||
if ((shuttleSteering?.SteeringPath != null && shuttleSteering.SteeringPath.Finished)
|
||||
|| (respawnShuttle.WorldPosition.Y + respawnShuttle.Borders.Y > Level.Loaded.StartPosition.Y - Level.ShaftHeight &&
|
||||
Math.Abs(Level.Loaded.StartPosition.X - respawnShuttle.WorldPosition.X) < 1000.0f))
|
||||
|| (RespawnShuttle.WorldPosition.Y + RespawnShuttle.Borders.Y > Level.Loaded.StartPosition.Y - Level.ShaftHeight &&
|
||||
Math.Abs(Level.Loaded.StartPosition.X - RespawnShuttle.WorldPosition.X) < 1000.0f))
|
||||
{
|
||||
CoroutineManager.StopCoroutines("forcepos");
|
||||
CoroutineManager.StartCoroutine(
|
||||
@@ -149,46 +164,60 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
if (respawnShuttle.WorldPosition.Y > Level.Loaded.Size.Y || shuttleReturnTimer <= 0.0f)
|
||||
if (RespawnShuttle.WorldPosition.Y > Level.Loaded.Size.Y || DateTime.Now > despawnTime)
|
||||
{
|
||||
CoroutineManager.StopCoroutines("forcepos");
|
||||
|
||||
ResetShuttle();
|
||||
|
||||
state = State.Waiting;
|
||||
CurrentState = State.Waiting;
|
||||
GameServer.Log("The respawn shuttle has left.", ServerLog.MessageType.Spawning);
|
||||
GameMain.Server.CreateEntityEvent(this);
|
||||
|
||||
respawnTimer = GameMain.Server.ServerSettings.RespawnInterval;
|
||||
CountdownStarted = false;
|
||||
RespawnCountdownStarted = false;
|
||||
}
|
||||
}
|
||||
|
||||
partial void UpdateTransportingProjSpecific(float deltaTime)
|
||||
{
|
||||
//if there are no living chracters inside, transporting can be stopped immediately
|
||||
if (!Character.CharacterList.Any(c => c.Submarine == respawnShuttle && !c.IsDead))
|
||||
|
||||
if (!ReturnCountdownStarted)
|
||||
{
|
||||
shuttleTransportTimer = 0.0f;
|
||||
//if there are no living chracters inside, transporting can be stopped immediately
|
||||
if (!Character.CharacterList.Any(c => c.Submarine == RespawnShuttle && !c.IsDead))
|
||||
{
|
||||
ReturnTime = DateTime.Now;
|
||||
ReturnCountdownStarted = true;
|
||||
}
|
||||
else if (!RespawnPending())
|
||||
{
|
||||
//don't start counting down until someone else needs to respawn
|
||||
ReturnTime = DateTime.Now + new TimeSpan(0, 0, 0, 0, milliseconds: (int)(maxTransportTime * 1000));
|
||||
despawnTime = ReturnTime + new TimeSpan(0, 0, seconds: 30);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
ReturnCountdownStarted = true;
|
||||
GameMain.Server.CreateEntityEvent(this);
|
||||
}
|
||||
}
|
||||
|
||||
if (shuttleTransportTimer <= 0.0f)
|
||||
if (DateTime.Now > ReturnTime)
|
||||
{
|
||||
GameServer.Log("The respawn shuttle is leaving.", ServerLog.MessageType.ServerMessage);
|
||||
state = State.Returning;
|
||||
CurrentState = State.Returning;
|
||||
|
||||
GameMain.Server.CreateEntityEvent(this);
|
||||
|
||||
CountdownStarted = false;
|
||||
RespawnCountdownStarted = false;
|
||||
maxTransportTime = GameMain.Server.ServerSettings.MaxTransportTime;
|
||||
shuttleReturnTimer = maxTransportTime;
|
||||
shuttleTransportTimer = maxTransportTime;
|
||||
}
|
||||
}
|
||||
|
||||
partial void RespawnCharactersProjSpecific()
|
||||
{
|
||||
var respawnSub = respawnShuttle ?? Submarine.MainSub;
|
||||
var respawnSub = RespawnShuttle ?? Submarine.MainSub;
|
||||
|
||||
var clients = GetClientsToRespawn();
|
||||
foreach (Client c in clients)
|
||||
@@ -250,7 +279,7 @@ namespace Barotrauma.Networking
|
||||
GameServer.Log(string.Format("Respawning {0} ({1}) as {2}", clients[i].Name, clients[i].Connection?.RemoteEndPoint?.Address, characterInfos[i].Job.Name), ServerLog.MessageType.Spawning);
|
||||
}
|
||||
|
||||
if (divingSuitPrefab != null && oxyPrefab != null && respawnShuttle != null)
|
||||
if (divingSuitPrefab != null && oxyPrefab != null && RespawnShuttle != null)
|
||||
{
|
||||
Vector2 pos = cargoSp == null ? character.Position : cargoSp.Position;
|
||||
if (divingSuitPrefab != null && oxyPrefab != null)
|
||||
@@ -295,5 +324,27 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null)
|
||||
{
|
||||
msg.WriteRangedInteger(0, Enum.GetNames(typeof(State)).Length, (int)CurrentState);
|
||||
|
||||
switch (CurrentState)
|
||||
{
|
||||
case State.Transporting:
|
||||
msg.Write(ReturnCountdownStarted);
|
||||
msg.Write(GameMain.Server.ServerSettings.MaxTransportTime);
|
||||
msg.Write((float)(ReturnTime - DateTime.Now).TotalSeconds);
|
||||
break;
|
||||
case State.Waiting:
|
||||
msg.Write(RespawnCountdownStarted);
|
||||
msg.Write((float)(RespawnTime - DateTime.Now).TotalSeconds);
|
||||
break;
|
||||
case State.Returning:
|
||||
break;
|
||||
}
|
||||
|
||||
msg.WritePadBits();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,8 +101,12 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (netProperties.ContainsKey(key))
|
||||
{
|
||||
object prevValue = netProperties[key].Value;
|
||||
netProperties[key].Read(incMsg);
|
||||
GameServer.Log(c.Name + " changed " + netProperties[key].Name + " to " + netProperties[key].Value.ToString(), ServerLog.MessageType.ServerMessage);
|
||||
if (!netProperties[key].PropEquals(prevValue, netProperties[key]))
|
||||
{
|
||||
GameServer.Log(c.Name + " changed " + netProperties[key].Name + " to " + netProperties[key].Value.ToString(), ServerLog.MessageType.ServerMessage);
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
else
|
||||
@@ -205,6 +209,12 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
doc.Save(writer);
|
||||
}
|
||||
|
||||
if (KarmaPreset == "custom")
|
||||
{
|
||||
GameMain.Server?.KarmaManager?.SaveCustomPreset();
|
||||
}
|
||||
GameMain.Server?.KarmaManager?.Save();
|
||||
}
|
||||
|
||||
private void LoadSettings()
|
||||
@@ -300,9 +310,6 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (!MonsterEnabled.ContainsKey(s)) MonsterEnabled.Add(s, true);
|
||||
}
|
||||
|
||||
AutoBanTime = doc.Root.GetAttributeFloat("autobantime", 60);
|
||||
MaxAutoBanTime = doc.Root.GetAttributeFloat("maxautobantime", 360);
|
||||
}
|
||||
|
||||
public void LoadClientPermissions()
|
||||
|
||||
Reference in New Issue
Block a user