Merge branch 'master' of https://github.com/Regalis11/Barotrauma.git into Regalis11-master
This commit is contained in:
@@ -64,5 +64,10 @@ namespace Barotrauma
|
||||
{
|
||||
GameMain.NetworkMember.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.UpdateMoney });
|
||||
}
|
||||
|
||||
partial void OnTalentGiven(string talentIdentifier)
|
||||
{
|
||||
GameServer.Log($"{GameServer.CharacterLogName(this)} has gained the talent '{talentIdentifier}'", ServerLog.MessageType.Talent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace Barotrauma
|
||||
if (Character == null || Character.Removed) { return; }
|
||||
if (prevAmount != newAmount)
|
||||
{
|
||||
GameServer.Log($"{GameServer.CharacterLogName(Character)} has gained {newAmount - prevAmount} experience ({prevAmount} -> {newAmount})", ServerLog.MessageType.Talent);
|
||||
GameMain.NetworkMember.CreateEntityEvent(Character, new object[] { NetEntityEvent.Type.UpdateExperience });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ namespace Barotrauma
|
||||
{
|
||||
ColoredText msg = queuedMessages.Dequeue();
|
||||
Messages.Add(msg);
|
||||
if (GameSettings.SaveDebugConsoleLogs)
|
||||
if (GameSettings.SaveDebugConsoleLogs || GameSettings.VerboseLogging)
|
||||
{
|
||||
unsavedMessages.Add(msg);
|
||||
if (unsavedMessages.Count >= messagesPerFile)
|
||||
@@ -269,7 +269,7 @@ namespace Barotrauma
|
||||
{
|
||||
string errorMsg = "Failed to write input to command line (window width: " + Console.WindowWidth + ", window height: " + Console.WindowHeight + ")\n"
|
||||
+ e.Message + "\n" + e.StackTrace.CleanupStackTrace();
|
||||
GameAnalyticsManager.AddErrorEventOnce("DebugConsole.RewriteInputToCommandLine", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("DebugConsole.RewriteInputToCommandLine", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ namespace Barotrauma
|
||||
{
|
||||
var msg = queuedMessages.Dequeue();
|
||||
Messages.Add(msg);
|
||||
if (GameSettings.SaveDebugConsoleLogs)
|
||||
if (GameSettings.SaveDebugConsoleLogs || GameSettings.VerboseLogging)
|
||||
{
|
||||
unsavedMessages.Add(msg);
|
||||
if (unsavedMessages.Count >= messagesPerFile)
|
||||
@@ -1331,7 +1331,7 @@ namespace Barotrauma
|
||||
|
||||
commands.Add(new Command("sub|submarine", "submarine [name]: Select the submarine for the next round.", (string[] args) =>
|
||||
{
|
||||
SubmarineInfo sub = GameMain.NetLobbyScreen.GetSubList().Find(s => s.Name.ToLower() == string.Join(" ", args).ToLower());
|
||||
SubmarineInfo sub = GameMain.NetLobbyScreen.GetSubList().Find(s => s.Name.Equals(string.Join(" ", args), StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (sub != null)
|
||||
{
|
||||
@@ -1393,7 +1393,7 @@ namespace Barotrauma
|
||||
|
||||
commands.Add(new Command("endgame|endround|end", "end/endgame/endround: End the current round.", (string[] args) =>
|
||||
{
|
||||
if (Screen.Selected == GameMain.NetLobbyScreen) return;
|
||||
if (Screen.Selected == GameMain.NetLobbyScreen) { return; }
|
||||
GameMain.Server.EndGame();
|
||||
}));
|
||||
|
||||
@@ -1415,11 +1415,18 @@ namespace Barotrauma
|
||||
|
||||
commands.Add(new Command("eventdata", "", (string[] args) =>
|
||||
{
|
||||
if (args.Length == 0) return;
|
||||
ServerEntityEvent ev = GameMain.Server.EntityEventManager.Events[Convert.ToUInt16(args[0])];
|
||||
if (args.Length == 0) { return; }
|
||||
if (!UInt16.TryParse(args[0], NumberStyles.Any, CultureInfo.InvariantCulture, out ushort eventId)) { return; }
|
||||
ServerEntityEvent ev = GameMain.Server.EntityEventManager.Events.Find(ev => ev.ID == eventId);
|
||||
if (ev != null)
|
||||
{
|
||||
NewMessage(ev.StackTrace.CleanupStackTrace(), Color.Lime);
|
||||
string entityData = "";
|
||||
if (ev.Entity is { ID: var entityId, Removed: var removed, IdFreed: var idFreed })
|
||||
{
|
||||
entityData = $"Entity ID: {entityId}; Entity removed: {removed}; Entity ID freed: {idFreed}";
|
||||
}
|
||||
NewMessage($"EventData {eventId}\n{entityData}", Color.Lime);
|
||||
//NewMessage(ev.StackTrace.CleanupStackTrace(), Color.Lime);
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -1594,16 +1601,9 @@ namespace Barotrauma
|
||||
(Client client, Vector2 cursorWorldPos, string[] args) =>
|
||||
{
|
||||
Character tpCharacter = (args.Length == 0) ? client.Character : FindMatchingCharacter(args, false);
|
||||
if (tpCharacter == null) return;
|
||||
|
||||
//var cam = GameMain.GameScreen.Cam;
|
||||
tpCharacter.AnimController.CurrentHull = null;
|
||||
tpCharacter.Submarine = null;
|
||||
tpCharacter.AnimController.SetPosition(ConvertUnits.ToSimUnits(cursorWorldPos));
|
||||
tpCharacter.AnimController.FindHull(cursorWorldPos, true);
|
||||
if (tpCharacter.AIController?.SteeringManager is IndoorsSteeringManager pathSteering)
|
||||
if (tpCharacter != null)
|
||||
{
|
||||
pathSteering.ResetPath();
|
||||
tpCharacter.TeleportTo(cursorWorldPos);
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -1795,7 +1795,7 @@ namespace Barotrauma
|
||||
List<TalentTree> talentTrees = new List<TalentTree>();
|
||||
if (args.Length == 0 || args[0].Equals("all", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
talentTrees.AddRange(TalentTree.JobTalentTrees.Values);
|
||||
talentTrees.AddRange(TalentTree.JobTalentTrees);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2386,6 +2386,16 @@ namespace Barotrauma
|
||||
GameMain.Server.CreateEntityEvent(wall);
|
||||
}
|
||||
}));
|
||||
commands.Add(new Command("stallfiletransfers", "stallfiletransfers [seconds]: A debug command that stalls each file transfer packet by the specified duration.", (string[] args) =>
|
||||
{
|
||||
float seconds = 0.0f;
|
||||
if (args.Length > 0)
|
||||
{
|
||||
float.TryParse(args[0], out seconds);
|
||||
}
|
||||
GameMain.Server.FileSender.StallPacketsTime = seconds;
|
||||
NewMessage("Set file transfer stall time to " + seconds);
|
||||
}));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Barotrauma.Networking;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
@@ -8,6 +7,8 @@ namespace Barotrauma
|
||||
{
|
||||
private readonly bool[] teamDead = new bool[2];
|
||||
|
||||
private List<Character>[] crews;
|
||||
|
||||
private bool initialized = false;
|
||||
|
||||
public override string Description
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using Barotrauma.Networking;
|
||||
using Barotrauma.Steam;
|
||||
using FarseerPhysics.Dynamics;
|
||||
using GameAnalyticsSDK.Net;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -101,8 +100,9 @@ namespace Barotrauma
|
||||
|
||||
Console.WriteLine("Initializing SteamManager");
|
||||
SteamManager.Initialize();
|
||||
Console.WriteLine("Initializing GameAnalytics");
|
||||
if (GameSettings.SendUserStatistics) GameAnalyticsManager.Init();
|
||||
//TODO: figure out how consent is supposed to work for servers
|
||||
//Console.WriteLine("Initializing GameAnalytics");
|
||||
//GameAnalyticsManager.InitIfConsented();
|
||||
|
||||
Console.WriteLine("Initializing GameScreen");
|
||||
GameScreen = new GameScreen();
|
||||
@@ -438,8 +438,8 @@ namespace Barotrauma
|
||||
|
||||
SaveUtil.CleanUnnecessarySaveFiles();
|
||||
|
||||
if (GameSettings.SaveDebugConsoleLogs) { DebugConsole.SaveLogs(); }
|
||||
if (GameSettings.SendUserStatistics) { GameAnalytics.OnQuit(); }
|
||||
if (GameSettings.SaveDebugConsoleLogs || GameSettings.VerboseLogging) { DebugConsole.SaveLogs(); }
|
||||
if (GameAnalyticsManager.SendUserStatistics) { GameAnalyticsManager.ShutDown(); }
|
||||
|
||||
MainThread = null;
|
||||
}
|
||||
@@ -451,7 +451,7 @@ namespace Barotrauma
|
||||
stopwatch?.Start();
|
||||
}
|
||||
|
||||
public CoroutineHandle ShowLoading(IEnumerable<object> loader, bool waitKeyHit = true)
|
||||
public CoroutineHandle ShowLoading(IEnumerable<CoroutineStatus> loader, bool waitKeyHit = true)
|
||||
{
|
||||
return CoroutineManager.StartCoroutine(loader);
|
||||
}
|
||||
|
||||
+1
-8
@@ -13,7 +13,7 @@ namespace Barotrauma
|
||||
get { return itemData != null; }
|
||||
}
|
||||
|
||||
public CharacterCampaignData(Client client, bool giveRespawnPenaltyAffliction = false)
|
||||
public CharacterCampaignData(Client client)
|
||||
{
|
||||
Name = client.Name;
|
||||
ClientEndPoint = client.Connection.EndPointString;
|
||||
@@ -22,13 +22,6 @@ namespace Barotrauma
|
||||
|
||||
healthData = new XElement("health");
|
||||
client.Character?.CharacterHealth?.Save(healthData);
|
||||
if (giveRespawnPenaltyAffliction)
|
||||
{
|
||||
var respawnPenaltyAffliction = RespawnManager.GetRespawnPenaltyAffliction();
|
||||
healthData.Add(new XElement("Affliction",
|
||||
new XAttribute("identifier", respawnPenaltyAffliction.Identifier),
|
||||
new XAttribute("strength", respawnPenaltyAffliction.Strength.ToString("G", CultureInfo.InvariantCulture))));
|
||||
}
|
||||
if (client.Character?.Inventory != null)
|
||||
{
|
||||
itemData = new XElement("inventory");
|
||||
|
||||
+49
-34
@@ -211,18 +211,6 @@ namespace Barotrauma
|
||||
{
|
||||
c.Character = null;
|
||||
}
|
||||
|
||||
if (c.HasSpawned && c.CharacterInfo != null && c.CharacterInfo.CauseOfDeath != null && c.CharacterInfo.CauseOfDeath.Type != CauseOfDeathType.Disconnected)
|
||||
{
|
||||
//the client has opted to spawn this round with Reaper's Tax
|
||||
if (c.WaitForNextRoundRespawn.HasValue && !c.WaitForNextRoundRespawn.Value)
|
||||
{
|
||||
c.CharacterInfo.StartItemsGiven = false;
|
||||
characterData.RemoveAll(cd => cd.MatchesClient(c));
|
||||
characterData.Add(new CharacterCampaignData(c, giveRespawnPenaltyAffliction: true));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
//use the info of the character the client is currently controlling
|
||||
// or the previously saved info if not (e.g. if the client has been spectating or died)
|
||||
var characterInfo = c.Character?.Info ?? characterData.Find(d => d.MatchesClient(c))?.CharacterInfo;
|
||||
@@ -231,6 +219,7 @@ namespace Barotrauma
|
||||
if (characterInfo.CauseOfDeath != null && characterInfo.CauseOfDeath.Type != CauseOfDeathType.Disconnected)
|
||||
{
|
||||
RespawnManager.ReduceCharacterSkills(characterInfo);
|
||||
characterInfo.RemoveSavedStatValuesOnDeath();
|
||||
}
|
||||
c.CharacterInfo = characterInfo;
|
||||
characterData.RemoveAll(cd => cd.MatchesClient(c));
|
||||
@@ -264,7 +253,7 @@ namespace Barotrauma
|
||||
if (c.Inventory == null) { continue; }
|
||||
if (Level.Loaded.Type == LevelData.LevelType.Outpost && c.Submarine != Level.Loaded.StartOutpost)
|
||||
{
|
||||
Map.CurrentLocation.RegisterTakenItems(c.Inventory.AllItems.Where(it => it.SpawnedInOutpost && it.OriginalModuleIndex > 0));
|
||||
Map.CurrentLocation.RegisterTakenItems(c.Inventory.AllItems.Where(it => it.SpawnedInCurrentOutpost && it.OriginalModuleIndex > 0));
|
||||
}
|
||||
|
||||
if (c.Info != null && c.IsBot)
|
||||
@@ -281,7 +270,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
protected override IEnumerable<object> DoLevelTransition(TransitionType transitionType, LevelData newLevel, Submarine leavingSub, bool mirror, List<TraitorMissionResult> traitorResults)
|
||||
protected override IEnumerable<CoroutineStatus> DoLevelTransition(TransitionType transitionType, LevelData newLevel, Submarine leavingSub, bool mirror, List<TraitorMissionResult> traitorResults)
|
||||
{
|
||||
lastUpdateID++;
|
||||
|
||||
@@ -358,6 +347,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
UpdateCampaignSubs();
|
||||
|
||||
SaveUtil.SaveGame(GameMain.GameSession.SavePath);
|
||||
PendingSubmarineSwitch = null;
|
||||
@@ -365,7 +355,7 @@ namespace Barotrauma
|
||||
else
|
||||
{
|
||||
PendingSubmarineSwitch = null;
|
||||
GameMain.Server.EndGame(TransitionType.None);
|
||||
GameMain.Server.EndGame(TransitionType.None, wasSaved: false);
|
||||
LoadCampaign(GameMain.GameSession.SavePath);
|
||||
LastSaveID++;
|
||||
LastUpdateID++;
|
||||
@@ -376,7 +366,7 @@ namespace Barotrauma
|
||||
|
||||
//--------------------------------------
|
||||
|
||||
GameMain.Server.EndGame(transitionType);
|
||||
GameMain.Server.EndGame(transitionType, wasSaved: true);
|
||||
|
||||
ForceMapUI = false;
|
||||
|
||||
@@ -400,20 +390,53 @@ namespace Barotrauma
|
||||
|
||||
partial void InitProjSpecific()
|
||||
{
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
CargoManager.OnItemsInBuyCrateChanged += () => { LastUpdateID++; };
|
||||
CargoManager.OnPurchasedItemsChanged += () => { LastUpdateID++; };
|
||||
CargoManager.OnSoldItemsChanged += () => { LastUpdateID++; };
|
||||
UpgradeManager.OnUpgradesChanged += () => { LastUpdateID++; };
|
||||
Map.OnLocationSelected += (loc, connection) => { LastUpdateID++; };
|
||||
Map.OnMissionsSelected += (loc, mission) => { LastUpdateID++; };
|
||||
Reputation.OnAnyReputationValueChanged += () => { LastUpdateID++; };
|
||||
}
|
||||
CargoManager.OnItemsInBuyCrateChanged += () => { LastUpdateID++; };
|
||||
CargoManager.OnPurchasedItemsChanged += () => { LastUpdateID++; };
|
||||
CargoManager.OnSoldItemsChanged += () => { LastUpdateID++; };
|
||||
UpgradeManager.OnUpgradesChanged += () => { LastUpdateID++; };
|
||||
Map.OnLocationSelected += (loc, connection) => { LastUpdateID++; };
|
||||
Map.OnMissionsSelected += (loc, mission) => { LastUpdateID++; };
|
||||
Reputation.OnAnyReputationValueChanged += () => { LastUpdateID++; };
|
||||
|
||||
UpdateCampaignSubs();
|
||||
|
||||
//increment save ID so clients know they're lacking the most up-to-date save file
|
||||
LastSaveID++;
|
||||
}
|
||||
|
||||
public static void UpdateCampaignSubs()
|
||||
{
|
||||
bool isSubmarineVisible(SubmarineInfo s)
|
||||
=> !GameMain.Server.ServerSettings.HiddenSubs.Any(h
|
||||
=> s.Name.Equals(h, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
List<SubmarineInfo> availableSubs =
|
||||
SubmarineInfo.SavedSubmarines
|
||||
.Where(s =>
|
||||
s.IsCampaignCompatible
|
||||
&& isSubmarineVisible(s))
|
||||
.ToList();
|
||||
|
||||
if (!availableSubs.Any())
|
||||
{
|
||||
//None of the available subs were marked as campaign-compatible, just include all visible subs
|
||||
availableSubs.AddRange(
|
||||
SubmarineInfo.SavedSubmarines
|
||||
.Where(isSubmarineVisible));
|
||||
}
|
||||
|
||||
if (!availableSubs.Any())
|
||||
{
|
||||
//No subs are visible at all! Just make the selected one available
|
||||
availableSubs.Add(GameMain.NetLobbyScreen.SelectedSub);
|
||||
}
|
||||
|
||||
GameMain.NetLobbyScreen.CampaignSubmarines = availableSubs;
|
||||
}
|
||||
|
||||
public bool CanPurchaseSub(SubmarineInfo info)
|
||||
=> info.Price <= Money && GameMain.NetLobbyScreen.CampaignSubmarines.Contains(info);
|
||||
|
||||
public void DiscardClientCharacterData(Client client)
|
||||
{
|
||||
characterData.RemoveAll(cd => cd.MatchesClient(client));
|
||||
@@ -1030,14 +1053,6 @@ namespace Barotrauma
|
||||
new XAttribute("points", savedExperiencePoint.ExperiencePoints)));
|
||||
}
|
||||
|
||||
// save available submarines
|
||||
XElement availableSubsElement = new XElement("AvailableSubs");
|
||||
for (int i = 0; i < GameMain.NetLobbyScreen.CampaignSubmarines.Count; i++)
|
||||
{
|
||||
availableSubsElement.Add(new XElement("Sub", new XAttribute("name", GameMain.NetLobbyScreen.CampaignSubmarines[i].Name)));
|
||||
}
|
||||
modeElement.Add(availableSubsElement);
|
||||
|
||||
element.Add(modeElement);
|
||||
|
||||
//save character data to a separate file
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<object> SendStateAfterDelay()
|
||||
private IEnumerable<CoroutineStatus> SendStateAfterDelay()
|
||||
{
|
||||
while (sendStateTimer > 0.0f)
|
||||
{
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<object> SendStateAfterDelay()
|
||||
private IEnumerable<CoroutineStatus> SendStateAfterDelay()
|
||||
{
|
||||
while (sendStateTimer > 0.0f)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using Barotrauma.Networking;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
@@ -20,6 +18,7 @@ namespace Barotrauma.Items.Components
|
||||
|
||||
public void ServerWrite(IWriteMessage msg, Client c, object[] extraData = null)
|
||||
{
|
||||
msg.Write(user?.ID ?? 0);
|
||||
msg.Write(IsActive);
|
||||
msg.Write(progressTimer);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class Reactor
|
||||
{
|
||||
const float NetworkUpdateIntervalLow = 10.0f;
|
||||
|
||||
private Client blameOnBroken;
|
||||
|
||||
private float? nextServerLogWriteTime;
|
||||
@@ -17,19 +19,19 @@ namespace Barotrauma.Items.Components
|
||||
float fissionRate = msg.ReadRangedSingle(0.0f, 100.0f, 8);
|
||||
float turbineOutput = msg.ReadRangedSingle(0.0f, 100.0f, 8);
|
||||
|
||||
if (!item.CanClientAccess(c)) return;
|
||||
if (!item.CanClientAccess(c)) { return; }
|
||||
|
||||
IsActive = true;
|
||||
|
||||
if (!autoTemp && AutoTemp) blameOnBroken = c;
|
||||
if (turbineOutput < targetTurbineOutput) blameOnBroken = c;
|
||||
if (fissionRate > targetFissionRate) blameOnBroken = c;
|
||||
if (turbineOutput < TargetTurbineOutput) blameOnBroken = c;
|
||||
if (fissionRate > TargetFissionRate) blameOnBroken = c;
|
||||
if (!_powerOn && powerOn) blameOnBroken = c;
|
||||
|
||||
AutoTemp = autoTemp;
|
||||
_powerOn = powerOn;
|
||||
targetFissionRate = fissionRate;
|
||||
targetTurbineOutput = turbineOutput;
|
||||
TargetFissionRate = fissionRate;
|
||||
TargetTurbineOutput = turbineOutput;
|
||||
|
||||
LastUser = c.Character;
|
||||
if (nextServerLogWriteTime == null)
|
||||
@@ -46,8 +48,8 @@ namespace Barotrauma.Items.Components
|
||||
msg.Write(autoTemp);
|
||||
msg.Write(_powerOn);
|
||||
msg.WriteRangedSingle(temperature, 0.0f, 100.0f, 8);
|
||||
msg.WriteRangedSingle(targetFissionRate, 0.0f, 100.0f, 8);
|
||||
msg.WriteRangedSingle(targetTurbineOutput, 0.0f, 100.0f, 8);
|
||||
msg.WriteRangedSingle(TargetFissionRate, 0.0f, 100.0f, 8);
|
||||
msg.WriteRangedSingle(TargetTurbineOutput, 0.0f, 100.0f, 8);
|
||||
msg.WriteRangedSingle(degreeOfSuccess, 0.0f, 1.0f, 8);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
if (c.Character == null) { return; }
|
||||
var requestedFixAction = (FixActions)msg.ReadRangedInteger(0, 2);
|
||||
var QTESuccess = msg.ReadBoolean();
|
||||
if (requestedFixAction != FixActions.None)
|
||||
{
|
||||
if (!c.Character.IsTraitor && requestedFixAction == FixActions.Sabotage)
|
||||
@@ -31,6 +32,11 @@ namespace Barotrauma.Items.Components
|
||||
item.CreateServerEvent(this);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RepairBoost(QTESuccess);
|
||||
item.CreateServerEvent(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void ServerWrite(IWriteMessage msg, Client c, object[] extraData = null)
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Barotrauma.Items.Components
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<object> SendStateAfterDelay()
|
||||
private IEnumerable<CoroutineStatus> SendStateAfterDelay()
|
||||
{
|
||||
while (sendStateTimer > 0.0f)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Barotrauma.Networking;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
@@ -19,17 +20,17 @@ namespace Barotrauma.Items.Components
|
||||
GameServer.Log(GameServer.CharacterLogName(c.Character) + " entered \"" + newOutputValue + "\" on " + item.Name,
|
||||
ServerLog.MessageType.ItemInteraction);
|
||||
OutputValue = newOutputValue;
|
||||
ShowOnDisplay(newOutputValue, addToHistory: true);
|
||||
ShowOnDisplay(newOutputValue, addToHistory: true, TextColor);
|
||||
item.SendSignal(newOutputValue, "signal_out");
|
||||
item.CreateServerEvent(this);
|
||||
}
|
||||
}
|
||||
|
||||
partial void ShowOnDisplay(string input, bool addToHistory)
|
||||
partial void ShowOnDisplay(string input, bool addToHistory, Color color)
|
||||
{
|
||||
if (addToHistory)
|
||||
{
|
||||
messageHistory.Add(input);
|
||||
messageHistory.Add(new TerminalMessage(input, color));
|
||||
while (messageHistory.Count > MaxMessages)
|
||||
{
|
||||
messageHistory.RemoveAt(0);
|
||||
@@ -41,7 +42,7 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
//split too long messages to multiple parts
|
||||
int msgIndex = 0;
|
||||
foreach (string str in messageHistory)
|
||||
foreach (var (str, _) in messageHistory)
|
||||
{
|
||||
string msgToSend = str;
|
||||
if (string.IsNullOrEmpty(msgToSend))
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
using Barotrauma.Networking;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class TriggerComponent : ItemComponent, IServerSerializable
|
||||
{
|
||||
public void ServerWrite(IWriteMessage msg, Client c, object[] extraData = null)
|
||||
{
|
||||
msg.WriteRangedSingle(CurrentForceFluctuation, 0.0f, 1.0f, 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,7 +41,7 @@ namespace Barotrauma
|
||||
}
|
||||
msg.WriteRangedInteger((int)NetEntityEvent.Type.Invalid, 0, Enum.GetValues(typeof(NetEntityEvent.Type)).Length - 1);
|
||||
DebugConsole.Log(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("Item.ServerWrite:InvalidData" + Name, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("Item.ServerWrite:InvalidData" + Name, GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ namespace Barotrauma
|
||||
msg.LengthBits = initialWritePos;
|
||||
msg.WriteRangedInteger((int)NetEntityEvent.Type.Invalid, 0, Enum.GetValues(typeof(NetEntityEvent.Type)).Length - 1);
|
||||
DebugConsole.Log(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("Item.ServerWrite:" + errorMsg, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("Item.ServerWrite:" + errorMsg, GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,7 +280,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
msg.Write(body == null ? (byte)0 : (byte)body.BodyType);
|
||||
msg.Write(SpawnedInOutpost);
|
||||
msg.Write(SpawnedInCurrentOutpost);
|
||||
msg.Write(AllowStealing);
|
||||
msg.WriteRangedInteger(Quality, 0, Items.Components.Quality.MaxQuality);
|
||||
|
||||
@@ -402,7 +402,7 @@ namespace Barotrauma
|
||||
{
|
||||
string errorMsg = "Attempted to create a network event for an item (" + Name + ") that hasn't been fully initialized yet.\n" + Environment.StackTrace.CleanupStackTrace();
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("Item.CreateServerEvent:EventForUninitializedItem" + Name + ID, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("Item.CreateServerEvent:EventForUninitializedItem" + Name + ID, GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -423,7 +423,7 @@ namespace Barotrauma
|
||||
{
|
||||
string errorMsg = "Attempted to create a network event for an item (" + Name + ") that hasn't been fully initialized yet.\n" + Environment.StackTrace.CleanupStackTrace();
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("Item.CreateServerEvent:EventForUninitializedItem" + Name + ID, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("Item.CreateServerEvent:EventForUninitializedItem" + Name + ID, GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
|
||||
message.Write(false);
|
||||
message.Write(false); //not a ballast flora update
|
||||
message.WriteRangedSingle(MathHelper.Clamp(waterVolume / Volume, 0.0f, 1.5f), 0.0f, 1.5f, 8);
|
||||
message.WriteRangedSingle(MathHelper.Clamp(OxygenPercentage, 0.0f, 100.0f), 0.0f, 100.0f, 8);
|
||||
|
||||
|
||||
@@ -274,6 +274,8 @@ namespace Barotrauma.Networking
|
||||
public void Save()
|
||||
{
|
||||
GameServer.Log("Saving banlist", ServerLog.MessageType.ServerMessage);
|
||||
|
||||
GameMain.Server?.ServerSettings?.UpdateFlag(ServerSettings.NetFlags.Properties);
|
||||
|
||||
bannedPlayers.RemoveAll(bp => bp.ExpirationTime.HasValue && DateTime.Now > bp.ExpirationTime.Value);
|
||||
|
||||
@@ -344,7 +346,7 @@ namespace Barotrauma.Networking
|
||||
catch (Exception e)
|
||||
{
|
||||
string errorMsg = "Error while writing banlist. {" + e + "}\n" + e.StackTrace.CleanupStackTrace();
|
||||
GameAnalyticsManager.AddErrorEventOnce("Banlist.ServerAdminWrite", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("Banlist.ServerAdminWrite", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,9 @@ namespace Barotrauma.Networking
|
||||
|
||||
public UInt16 LastRecvClientListUpdate = 0;
|
||||
|
||||
public UInt16 LastSentServerSettingsUpdate = 0;
|
||||
public UInt16 LastRecvServerSettingsUpdate = 0;
|
||||
|
||||
public UInt16 LastRecvLobbyUpdate = 0;
|
||||
|
||||
public UInt16 LastSentChatMsgID = 0; //last msg this client said
|
||||
@@ -133,12 +136,14 @@ namespace Barotrauma.Networking
|
||||
|
||||
public static bool IsValidName(string name, ServerSettings serverSettings)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(name)) { return false; }
|
||||
|
||||
char[] disallowedChars = new char[] { ';', ',', '<', '>', '/', '\\', '[', ']', '"', '?' };
|
||||
if (name.Any(c => disallowedChars.Contains(c))) return false;
|
||||
if (name.Any(c => disallowedChars.Contains(c))) { return false; }
|
||||
|
||||
foreach (char character in name)
|
||||
{
|
||||
if (!serverSettings.AllowedClientNameChars.Any(charRange => (int)character >= charRange.First && (int)character <= charRange.Second)) return false;
|
||||
if (!serverSettings.AllowedClientNameChars.Any(charRange => (int)character >= charRange.First && (int)character <= charRange.Second)) { return false; }
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -108,6 +108,10 @@ namespace Barotrauma.Networking
|
||||
|
||||
private readonly ServerPeer peer;
|
||||
|
||||
#if DEBUG
|
||||
public float StallPacketsTime { get; set; }
|
||||
#endif
|
||||
|
||||
public List<FileTransferOut> ActiveTransfers
|
||||
{
|
||||
get { return activeTransfers; }
|
||||
@@ -264,6 +268,9 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
peer.Send(message, transfer.Connection, DeliveryMethod.Unreliable);
|
||||
#if DEBUG
|
||||
transfer.WaitTimer = Math.Max(transfer.WaitTimer, StallPacketsTime);
|
||||
#endif
|
||||
}
|
||||
|
||||
catch (Exception e)
|
||||
@@ -271,7 +278,7 @@ namespace Barotrauma.Networking
|
||||
DebugConsole.ThrowError("FileSender threw an exception when trying to send data", e);
|
||||
GameAnalyticsManager.AddErrorEventOnce(
|
||||
"FileSender.Update:Exception",
|
||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
GameAnalyticsManager.ErrorSeverity.Error,
|
||||
"FileSender threw an exception when trying to send data:\n" + e.Message + "\n" + e.StackTrace.CleanupStackTrace());
|
||||
transfer.Status = FileTransferStatus.Error;
|
||||
return;
|
||||
|
||||
@@ -77,6 +77,11 @@ namespace Barotrauma.Networking
|
||||
private readonly ServerEntityEventManager entityEventManager;
|
||||
|
||||
private FileSender fileSender;
|
||||
|
||||
public FileSender FileSender
|
||||
{
|
||||
get { return fileSender; }
|
||||
}
|
||||
#if DEBUG
|
||||
public void PrintSenderTransters()
|
||||
{
|
||||
@@ -141,7 +146,7 @@ namespace Barotrauma.Networking
|
||||
CoroutineManager.StartCoroutine(StartServer(isPublic));
|
||||
}
|
||||
|
||||
private IEnumerable<object> StartServer(bool isPublic)
|
||||
private IEnumerable<CoroutineStatus> StartServer(bool isPublic)
|
||||
{
|
||||
bool error = false;
|
||||
try
|
||||
@@ -401,7 +406,7 @@ namespace Barotrauma.Networking
|
||||
character.SetStun(1.0f);
|
||||
}
|
||||
|
||||
Client owner = connectedClients.Find(c => c.EndpointMatches(character.OwnerClientEndPoint));
|
||||
Client owner = connectedClients.Find(c => (c.Character == null || c.Character == character) && c.EndpointMatches(character.OwnerClientEndPoint));
|
||||
|
||||
if ((OwnerConnection == null || owner?.Connection != OwnerConnection) && character.KillDisconnectedTimer > serverSettings.KillDisconnectedTime)
|
||||
{
|
||||
@@ -496,7 +501,7 @@ namespace Barotrauma.Networking
|
||||
else if (isCrewDead && (GameMain.GameSession?.GameMode is CampaignMode))
|
||||
{
|
||||
#if !DEBUG
|
||||
endRoundDelay = 1.0f;
|
||||
endRoundDelay = 2.0f;
|
||||
endRoundTimer += deltaTime;
|
||||
#endif
|
||||
}
|
||||
@@ -527,7 +532,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
Log("Ending round (no living players left)", ServerLog.MessageType.ServerMessage);
|
||||
}
|
||||
EndGame();
|
||||
EndGame(wasSaved: false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -605,16 +610,19 @@ namespace Barotrauma.Networking
|
||||
//constantly increase AFK timer if the client is controlling a character (gets reset to zero every time an input is received)
|
||||
if (gameStarted && c.Character != null && !c.Character.IsDead && !c.Character.IsIncapacitated)
|
||||
{
|
||||
if (c.Connection != OwnerConnection) c.KickAFKTimer += deltaTime;
|
||||
if (c.Connection != OwnerConnection && c.Permissions != ClientPermissions.All) { c.KickAFKTimer += deltaTime; }
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerable<Client> kickAFK = connectedClients.FindAll(c =>
|
||||
c.KickAFKTimer >= serverSettings.KickAFKTime &&
|
||||
(OwnerConnection == null || c.Connection != OwnerConnection));
|
||||
foreach (Client c in kickAFK)
|
||||
if (connectedClients.Any(c => c.KickAFKTimer >= serverSettings.KickAFKTime))
|
||||
{
|
||||
KickClient(c, "DisconnectMessage.AFK");
|
||||
IEnumerable<Client> kickAFK = connectedClients.FindAll(c =>
|
||||
c.KickAFKTimer >= serverSettings.KickAFKTime &&
|
||||
(OwnerConnection == null || c.Connection != OwnerConnection));
|
||||
foreach (Client c in kickAFK)
|
||||
{
|
||||
KickClient(c, "DisconnectMessage.AFK");
|
||||
}
|
||||
}
|
||||
|
||||
serverPeer.Update(deltaTime);
|
||||
@@ -637,7 +645,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to write a network message for the client \"" + c.Name + "\"!", e);
|
||||
|
||||
string errorMsg = "Failed to write a network message for the client \"" + c.Name + "\"! (MidRoundSyncing: " + c.NeedsMidRoundSync + ")\n"
|
||||
string errorMsg = "Failed to write a network message for a client! (MidRoundSyncing: " + c.NeedsMidRoundSync + ")\n"
|
||||
+ e.Message + "\n" + e.StackTrace.CleanupStackTrace();
|
||||
if (e.InnerException != null)
|
||||
{
|
||||
@@ -646,7 +654,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
GameAnalyticsManager.AddErrorEventOnce(
|
||||
"GameServer.Update:ClientWriteFailed" + e.StackTrace.CleanupStackTrace(),
|
||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
GameAnalyticsManager.ErrorSeverity.Error,
|
||||
errorMsg);
|
||||
}
|
||||
}
|
||||
@@ -796,6 +804,8 @@ namespace Barotrauma.Networking
|
||||
string localSavePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Multiplayer, saveName);
|
||||
if (connectedClient.HasPermission(ClientPermissions.SelectMode) || connectedClient.HasPermission(ClientPermissions.ManageCampaign))
|
||||
{
|
||||
ServerSettings.RadiationEnabled = settings.RadiationEnabled;
|
||||
ServerSettings.MaxMissionCount = settings.MaxMissionCount;
|
||||
MultiPlayerCampaign.StartNewCampaign(localSavePath, matchingSub.FilePath, seed, settings);
|
||||
}
|
||||
}
|
||||
@@ -862,6 +872,7 @@ namespace Barotrauma.Networking
|
||||
private void HandleClientError(IReadMessage inc, Client c)
|
||||
{
|
||||
string errorStr = "Unhandled error report";
|
||||
string errorStrNoName = errorStr;
|
||||
|
||||
ClientNetError error = (ClientNetError)inc.ReadByte();
|
||||
switch (error)
|
||||
@@ -869,7 +880,7 @@ namespace Barotrauma.Networking
|
||||
case ClientNetError.MISSING_EVENT:
|
||||
UInt16 expectedID = inc.ReadUInt16();
|
||||
UInt16 receivedID = inc.ReadUInt16();
|
||||
errorStr = "Expecting event id " + expectedID.ToString() + ", received " + receivedID.ToString();
|
||||
errorStr = errorStrNoName = "Expecting event id " + expectedID.ToString() + ", received " + receivedID.ToString();
|
||||
break;
|
||||
case ClientNetError.MISSING_ENTITY:
|
||||
UInt16 eventID = inc.ReadUInt16();
|
||||
@@ -877,25 +888,26 @@ namespace Barotrauma.Networking
|
||||
Entity entity = Entity.FindEntityByID(entityID);
|
||||
if (entity == null)
|
||||
{
|
||||
errorStr = "Received an update for an entity that doesn't exist (event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ").";
|
||||
errorStr = errorStrNoName = "Received an update for an entity that doesn't exist (event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ").";
|
||||
}
|
||||
else if (entity is Character character)
|
||||
{
|
||||
errorStr = "Missing character " + character.Name + " (event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ").";
|
||||
errorStrNoName = "Missing character " + character.SpeciesName + "(event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ").";
|
||||
}
|
||||
else if (entity is Item item)
|
||||
{
|
||||
errorStr = "Missing item " + item.Name + " (event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ").";
|
||||
errorStr = errorStrNoName = "Missing item " + item.Name + " (event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ").";
|
||||
}
|
||||
else
|
||||
{
|
||||
errorStr = "Missing entity " + entity.ToString() + " (event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ").";
|
||||
errorStr = errorStrNoName = "Missing entity " + entity.ToString() + " (event id " + eventID.ToString() + ", entity id " + entityID.ToString() + ").";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
Log(GameServer.ClientLogName(c) + " has reported an error: " + errorStr, ServerLog.MessageType.Error);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.HandleClientError:" + errorStr, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorStr);
|
||||
Log(ClientLogName(c) + " has reported an error: " + errorStr, ServerLog.MessageType.Error);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.HandleClientError:" + errorStrNoName, GameAnalyticsManager.ErrorSeverity.Error, errorStr);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -909,7 +921,7 @@ namespace Barotrauma.Networking
|
||||
if (c.Connection == OwnerConnection)
|
||||
{
|
||||
SendDirectChatMessage(errorStr, c, ChatMessageType.MessageBox);
|
||||
EndGame();
|
||||
EndGame(wasSaved: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1002,8 +1014,11 @@ namespace Barotrauma.Networking
|
||||
|
||||
public override void CreateEntityEvent(INetSerializable entity, object[] extraData = null)
|
||||
{
|
||||
if (!(entity is IServerSerializable)) throw new InvalidCastException("entity is not IServerSerializable");
|
||||
entityEventManager.CreateEvent(entity as IServerSerializable, extraData);
|
||||
if (!(entity is IServerSerializable serverSerializable))
|
||||
{
|
||||
throw new InvalidCastException($"Entity is not {nameof(IServerSerializable)}");
|
||||
}
|
||||
entityEventManager.CreateEvent(serverSerializable, extraData);
|
||||
}
|
||||
|
||||
private byte GetNewClientID()
|
||||
@@ -1034,6 +1049,11 @@ namespace Barotrauma.Networking
|
||||
case ClientNetObject.SYNC_IDS:
|
||||
//TODO: might want to use a clever class for this
|
||||
c.LastRecvLobbyUpdate = NetIdUtils.Clamp(inc.ReadUInt16(), c.LastRecvLobbyUpdate, GameMain.NetLobbyScreen.LastUpdateID);
|
||||
if (c.HasPermission(ClientPermissions.ManageSettings) &&
|
||||
NetIdUtils.IdMoreRecentOrMatches(c.LastRecvLobbyUpdate, c.LastSentServerSettingsUpdate))
|
||||
{
|
||||
c.LastRecvServerSettingsUpdate = c.LastSentServerSettingsUpdate;
|
||||
}
|
||||
c.LastRecvChatMsgID = NetIdUtils.Clamp(inc.ReadUInt16(), c.LastRecvChatMsgID, c.LastChatMsgQueueID);
|
||||
c.LastRecvClientListUpdate = NetIdUtils.Clamp(inc.ReadUInt16(), c.LastRecvClientListUpdate, LastClientListUpdateID);
|
||||
|
||||
@@ -1142,6 +1162,8 @@ namespace Barotrauma.Networking
|
||||
lastRecvEntityEventID = (UInt16)(c.FirstNewEventID - 1);
|
||||
c.LastRecvEntityEventID = lastRecvEntityEventID;
|
||||
DebugConsole.Log("Finished midround syncing " + c.Name + " - switching from ID " + prevID + " to " + c.LastRecvEntityEventID);
|
||||
//notify the client of the state of the respawn manager (so they show the respawn prompt if needed)
|
||||
if (respawnManager != null) { CreateEntityEvent(respawnManager); }
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1328,18 +1350,23 @@ namespace Barotrauma.Networking
|
||||
break;
|
||||
case ClientPermissions.ManageRound:
|
||||
bool end = inc.ReadBoolean();
|
||||
bool save = inc.ReadBoolean();
|
||||
if (end)
|
||||
{
|
||||
if (gameStarted)
|
||||
{
|
||||
Log("Client \"" + GameServer.ClientLogName(sender) + "\" ended the round.", ServerLog.MessageType.ServerMessage);
|
||||
if (mpCampaign != null && Level.IsLoadedOutpost)
|
||||
if (mpCampaign != null && Level.IsLoadedOutpost && save)
|
||||
{
|
||||
mpCampaign.SavePlayers();
|
||||
GameMain.GameSession.SubmarineInfo = new SubmarineInfo(GameMain.GameSession.Submarine);
|
||||
SaveUtil.SaveGame(GameMain.GameSession.SavePath);
|
||||
GameMain.GameSession.SubmarineInfo = new SubmarineInfo(GameMain.GameSession.Submarine);
|
||||
SaveUtil.SaveGame(GameMain.GameSession.SavePath);
|
||||
}
|
||||
EndGame();
|
||||
else
|
||||
{
|
||||
save = false;
|
||||
}
|
||||
EndGame(wasSaved: save);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1390,49 +1417,23 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
break;
|
||||
case ClientPermissions.SelectSub:
|
||||
bool isCampaign = inc.ReadBoolean();
|
||||
if (!isCampaign)
|
||||
bool isShuttle = inc.ReadBoolean();
|
||||
inc.ReadPadBits();
|
||||
UInt16 subIndex = inc.ReadUInt16();
|
||||
var subList = GameMain.NetLobbyScreen.GetSubList();
|
||||
if (subIndex >= subList.Count)
|
||||
{
|
||||
bool isShuttle = inc.ReadBoolean();
|
||||
inc.ReadPadBits();
|
||||
UInt16 subIndex = inc.ReadUInt16();
|
||||
var subList = GameMain.NetLobbyScreen.GetSubList();
|
||||
if (subIndex >= subList.Count)
|
||||
{
|
||||
DebugConsole.NewMessage("Client \"" + GameServer.ClientLogName(sender) + "\" attempted to select a sub, index out of bounds (" + subIndex + ")", Color.Red);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isShuttle)
|
||||
{
|
||||
GameMain.NetLobbyScreen.SelectedShuttle = subList[subIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMain.NetLobbyScreen.SelectedSub = subList[subIndex];
|
||||
}
|
||||
}
|
||||
DebugConsole.NewMessage($"Client \"{ClientLogName(sender)}\" attempted to select a sub, index out of bounds ({subIndex})", Color.Red);
|
||||
}
|
||||
else
|
||||
{
|
||||
int subEqualityCheckVal = inc.ReadInt32();
|
||||
bool add = inc.ReadBoolean();
|
||||
SubmarineInfo sub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.EqualityCheckVal == subEqualityCheckVal);
|
||||
|
||||
if (sub == null)
|
||||
if (isShuttle)
|
||||
{
|
||||
DebugConsole.NewMessage("Client \"" + GameServer.ClientLogName(sender) + "\" attempted to select a sub that does not exist on the server!", Color.Red);
|
||||
GameMain.NetLobbyScreen.SelectedShuttle = subList[subIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (add)
|
||||
{
|
||||
GameMain.NetLobbyScreen.AddCampaignSubmarine(sub);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMain.NetLobbyScreen.RemoveCampaignSubmarine(sub);
|
||||
}
|
||||
GameMain.NetLobbyScreen.SelectedSub = subList[subIndex];
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1749,7 +1750,7 @@ namespace Barotrauma.Networking
|
||||
" Chat message size: " + chatMessageBytes + " bytes\n" +
|
||||
" Position update size: " + positionUpdateBytes + " bytes\n\n";
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.ClientWriteIngame1:PacketSizeExceeded" + outmsg.LengthBytes, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.ClientWriteIngame1:PacketSizeExceeded" + outmsg.LengthBytes, GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
}
|
||||
|
||||
serverPeer.Send(outmsg, c.Connection, DeliveryMethod.Unreliable);
|
||||
@@ -1789,7 +1790,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.ClientWriteIngame2:PacketSizeExceeded" + outmsg.LengthBytes, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.ClientWriteIngame2:PacketSizeExceeded" + outmsg.LengthBytes, GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
}
|
||||
|
||||
serverPeer.Send(outmsg, c.Connection, DeliveryMethod.Unreliable);
|
||||
@@ -1876,7 +1877,7 @@ namespace Barotrauma.Networking
|
||||
List<int> campaignSubIndices = new List<int>();
|
||||
if (GameMain.NetLobbyScreen.SelectedMode == GameModePreset.MultiPlayerCampaign)
|
||||
{
|
||||
List<SubmarineInfo> subList = GameMain.NetLobbyScreen.GetSubList();
|
||||
IReadOnlyList<SubmarineInfo> subList = GameMain.NetLobbyScreen.GetSubList();
|
||||
for (int i = 0; i < subList.Count; i++)
|
||||
{
|
||||
if (GameMain.NetLobbyScreen.CampaignSubmarines.Contains(subList[i]))
|
||||
@@ -1914,9 +1915,6 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
outmsg.Write(autoRestartTimerRunning ? serverSettings.AutoRestartTimer : 0.0f);
|
||||
}
|
||||
|
||||
outmsg.Write(serverSettings.RadiationEnabled);
|
||||
outmsg.Write((byte)serverSettings.MaxMissionCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1956,8 +1954,31 @@ namespace Barotrauma.Networking
|
||||
chatMessageBytes = outmsg.LengthBytes - outmsg.LengthBytes;
|
||||
|
||||
outmsg.Write((byte)ServerNetObject.END_OF_MESSAGE);
|
||||
|
||||
if (isInitialUpdate)
|
||||
|
||||
bool messageTooLarge = outmsg.LengthBytes > MsgConstants.MTU;
|
||||
if (messageTooLarge && !isInitialUpdate)
|
||||
{
|
||||
string warningMsg = "Maximum packet size exceeded, will send using reliable mode (" + outmsg.LengthBytes + " > " + MsgConstants.MTU + ")\n";
|
||||
warningMsg +=
|
||||
" Client list size: " + clientListBytes + " bytes\n" +
|
||||
" Chat message size: " + chatMessageBytes + " bytes\n" +
|
||||
" Campaign size: " + campaignBytes + " bytes\n" +
|
||||
" Settings size: " + settingsBytes + " bytes\n";
|
||||
if (initialUpdateBytes > 0)
|
||||
{
|
||||
warningMsg +=
|
||||
" Initial update size: " + settingsBuf.LengthBytes + " bytes\n";
|
||||
}
|
||||
if (settingsBuf != null)
|
||||
{
|
||||
warningMsg +=
|
||||
" Settings buffer size: " + settingsBuf.LengthBytes + " bytes\n";
|
||||
}
|
||||
if (GameSettings.VerboseLogging) { DebugConsole.AddWarning(warningMsg); }
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.ClientWriteIngame1:ClientWriteLobby" + outmsg.LengthBytes, GameAnalyticsManager.ErrorSeverity.Warning, warningMsg);
|
||||
}
|
||||
|
||||
if (isInitialUpdate || messageTooLarge)
|
||||
{
|
||||
//the initial update may be very large if the host has a large number
|
||||
//of submarine files, so the message may have to be fragmented
|
||||
@@ -1973,28 +1994,6 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
else
|
||||
{
|
||||
if (outmsg.LengthBytes > MsgConstants.MTU)
|
||||
{
|
||||
string errorMsg = "Maximum packet size exceeded (" + outmsg.LengthBytes + " > " + MsgConstants.MTU + ")\n";
|
||||
errorMsg +=
|
||||
" Client list size: " + clientListBytes + " bytes\n" +
|
||||
" Chat message size: " + chatMessageBytes + " bytes\n" +
|
||||
" Campaign size: " + campaignBytes + " bytes\n" +
|
||||
" Settings size: " + settingsBytes + " bytes\n";
|
||||
if (initialUpdateBytes > 0)
|
||||
{
|
||||
errorMsg +=
|
||||
" Initial update size: " + settingsBuf.LengthBytes + " bytes\n";
|
||||
}
|
||||
if (settingsBuf != null)
|
||||
{
|
||||
errorMsg +=
|
||||
" Settings buffer size: " + settingsBuf.LengthBytes + " bytes\n";
|
||||
}
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.ClientWriteIngame1:ClientWriteLobby" + outmsg.LengthBytes, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
}
|
||||
|
||||
serverPeer.Send(outmsg, c.Connection, DeliveryMethod.Unreliable);
|
||||
}
|
||||
}
|
||||
@@ -2018,9 +2017,9 @@ namespace Barotrauma.Networking
|
||||
if (initiatedStartGame || gameStarted) { return false; }
|
||||
|
||||
Log("Starting a new round...", ServerLog.MessageType.ServerMessage);
|
||||
SubmarineInfo selectedSub = null;
|
||||
SubmarineInfo selectedShuttle = GameMain.NetLobbyScreen.SelectedShuttle;
|
||||
|
||||
SubmarineInfo selectedSub;
|
||||
if (serverSettings.Voting.AllowSubVoting)
|
||||
{
|
||||
selectedSub = serverSettings.Voting.HighestVoted<SubmarineInfo>(VoteType.Sub, connectedClients);
|
||||
@@ -2050,7 +2049,7 @@ namespace Barotrauma.Networking
|
||||
return true;
|
||||
}
|
||||
|
||||
private IEnumerable<object> InitiateStartGame(SubmarineInfo selectedSub, SubmarineInfo selectedShuttle, GameModePreset selectedMode)
|
||||
private IEnumerable<CoroutineStatus> InitiateStartGame(SubmarineInfo selectedSub, SubmarineInfo selectedShuttle, GameModePreset selectedMode)
|
||||
{
|
||||
initiatedStartGame = true;
|
||||
|
||||
@@ -2092,7 +2091,6 @@ namespace Barotrauma.Networking
|
||||
while (fileSender.ActiveTransfers.Count > 0 && waitForTransfersTimer > 0.0f)
|
||||
{
|
||||
waitForTransfersTimer -= CoroutineManager.UnscaledDeltaTime;
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
}
|
||||
}
|
||||
@@ -2103,7 +2101,7 @@ namespace Barotrauma.Networking
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
private IEnumerable<object> StartGame(SubmarineInfo selectedSub, SubmarineInfo selectedShuttle, GameModePreset selectedMode, CampaignSettings settings)
|
||||
private IEnumerable<CoroutineStatus> StartGame(SubmarineInfo selectedSub, SubmarineInfo selectedShuttle, GameModePreset selectedMode, CampaignSettings settings)
|
||||
{
|
||||
entityEventManager.Clear();
|
||||
|
||||
@@ -2120,7 +2118,7 @@ namespace Barotrauma.Networking
|
||||
startGameCoroutine = null;
|
||||
string errorMsg = "Starting the round failed. Campaign was still active, but the map has been disposed. Try selecting another game mode.";
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.StartGame:InvalidCampaignState", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.StartGame:InvalidCampaignState", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
if (OwnerConnection != null)
|
||||
{
|
||||
SendDirectChatMessage(errorMsg, connectedClients.Find(c => c.Connection == OwnerConnection), ChatMessageType.Error);
|
||||
@@ -2162,7 +2160,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
string errorMsg = "Failed to start a campaign round (next level not set).";
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.StartGame:InvalidCampaignState", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.StartGame:InvalidCampaignState", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
if (OwnerConnection != null)
|
||||
{
|
||||
SendDirectChatMessage(errorMsg, connectedClients.Find(c => c.Connection == OwnerConnection), ChatMessageType.Error);
|
||||
@@ -2398,6 +2396,22 @@ namespace Barotrauma.Networking
|
||||
// talents are only avilable for players in online sessions, but modders or someone else might want to have them loaded anyway
|
||||
spawnedCharacter.LoadTalents();
|
||||
}
|
||||
|
||||
spawnedCharacter.OwnerClientEndPoint = teamClients[i].Connection.EndPointString;
|
||||
spawnedCharacter.OwnerClientName = teamClients[i].Name;
|
||||
}
|
||||
|
||||
for (int i = teamClients.Count; i < teamClients.Count + bots.Count; i++)
|
||||
{
|
||||
Character spawnedCharacter = Character.Create(characterInfos[i], spawnWaypoints[i].WorldPosition, characterInfos[i].Name, isRemotePlayer: false, hasAi: true);
|
||||
spawnedCharacter.TeamID = teamID;
|
||||
spawnedCharacter.GiveJobItems(mainSubWaypoints[i]);
|
||||
spawnedCharacter.GiveIdCardTags(mainSubWaypoints[i]);
|
||||
spawnedCharacter.Info.InventoryData = new XElement("inventory");
|
||||
spawnedCharacter.Info.StartItemsGiven = true;
|
||||
spawnedCharacter.SaveInventory();
|
||||
// talents are only avilable for players in online sessions, but modders or someone else might want to have them loaded anyway
|
||||
spawnedCharacter.LoadTalents();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2498,8 +2512,9 @@ namespace Barotrauma.Networking
|
||||
msg.Write(serverSettings.AllowFriendlyFire);
|
||||
msg.Write(serverSettings.LockAllDefaultWires);
|
||||
msg.Write(serverSettings.AllowRagdollButton);
|
||||
msg.Write(serverSettings.AllowLinkingWifiToChat);
|
||||
msg.Write(serverSettings.UseRespawnShuttle);
|
||||
msg.Write((byte)GameMain.Config.LosMode);
|
||||
msg.Write((byte)serverSettings.LosMode);
|
||||
msg.Write(includesFinalize); msg.WritePadBits();
|
||||
|
||||
serverSettings.WriteMonsterEnabled(msg);
|
||||
@@ -2523,6 +2538,7 @@ namespace Barotrauma.Networking
|
||||
int nextLocationIndex = campaign.Map.Locations.FindIndex(l => l.LevelData == campaign.NextLevel);
|
||||
int nextConnectionIndex = campaign.Map.Connections.FindIndex(c => c.LevelData == campaign.NextLevel);
|
||||
msg.Write(campaign.CampaignID);
|
||||
msg.Write(campaign.LastSaveID);
|
||||
msg.Write(nextLocationIndex);
|
||||
msg.Write(nextConnectionIndex);
|
||||
msg.Write(campaign.Map.SelectedLocationIndex);
|
||||
@@ -2574,7 +2590,7 @@ namespace Barotrauma.Networking
|
||||
GameMain.GameSession.CrewManager?.ServerWriteActiveOrders(msg);
|
||||
}
|
||||
|
||||
public void EndGame(CampaignMode.TransitionType transitionType = CampaignMode.TransitionType.None)
|
||||
public void EndGame(CampaignMode.TransitionType transitionType = CampaignMode.TransitionType.None, bool wasSaved = false)
|
||||
{
|
||||
if (!gameStarted)
|
||||
{
|
||||
@@ -2638,6 +2654,7 @@ namespace Barotrauma.Networking
|
||||
IWriteMessage msg = new WriteOnlyMessage();
|
||||
msg.Write((byte)ServerPacketHeader.ENDGAME);
|
||||
msg.Write((byte)transitionType);
|
||||
msg.Write(wasSaved);
|
||||
msg.Write(endMessage);
|
||||
msg.Write((byte)missions.Count);
|
||||
foreach (Mission mission in missions)
|
||||
@@ -2967,7 +2984,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
string errorMsg = "Attempted to send a chat message to a null client.\n" + Environment.StackTrace.CleanupStackTrace();
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.SendDirectChatMessage:ClientNull", GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("GameServer.SendDirectChatMessage:ClientNull", GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3278,7 +3295,7 @@ namespace Barotrauma.Networking
|
||||
BanClient(c, "ServerMessage.KickedByVoteAutoBan", duration: TimeSpan.FromSeconds(serverSettings.AutoBanTime));
|
||||
}
|
||||
|
||||
GameMain.NetLobbyScreen.LastUpdateID++;
|
||||
//GameMain.NetLobbyScreen.LastUpdateID++;
|
||||
|
||||
SendVoteStatus(connectedClients);
|
||||
|
||||
@@ -3286,7 +3303,7 @@ namespace Barotrauma.Networking
|
||||
((float)EndVoteCount / (float)EndVoteMax) >= serverSettings.EndVoteRequiredRatio)
|
||||
{
|
||||
Log("Ending round by votes (" + EndVoteCount + "/" + (EndVoteMax - EndVoteCount) + ")", ServerLog.MessageType.ServerMessage);
|
||||
EndGame();
|
||||
EndGame(wasSaved: false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3368,7 +3385,7 @@ namespace Barotrauma.Networking
|
||||
serverSettings.SaveClientPermissions();
|
||||
}
|
||||
|
||||
private IEnumerable<object> SendClientPermissionsAfterClientListSynced(Client recipient, Client client)
|
||||
private IEnumerable<CoroutineStatus> SendClientPermissionsAfterClientListSynced(Client recipient, Client client)
|
||||
{
|
||||
DateTime timeOut = DateTime.Now + new TimeSpan(0, 0, 10);
|
||||
while (recipient.LastRecvClientListUpdate < LastClientListUpdateID)
|
||||
|
||||
@@ -43,6 +43,8 @@ namespace Barotrauma
|
||||
get;
|
||||
private set;
|
||||
} = new Dictionary<Character, double>();
|
||||
|
||||
public int DangerousItemsContained { get; set; }
|
||||
}
|
||||
|
||||
public bool TestMode = false;
|
||||
@@ -575,6 +577,25 @@ 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"))
|
||||
{
|
||||
var client = GameMain.Server.ConnectedClients.Find(c => c.Character == character);
|
||||
if (client == null) { return; }
|
||||
float amount = -DangerousItemContainKarmaDecrease;
|
||||
var memory = GetClientMemory(client);
|
||||
if (IsDangerousItemContainKarmaDecreaseIncremental)
|
||||
{
|
||||
amount *= memory.DangerousItemsContained;
|
||||
}
|
||||
amount = Math.Max(amount, -MaxDangerousItemContainKarmaDecrease);
|
||||
AdjustKarma(character, amount, "Put an oxygen tank inside a welding tool");
|
||||
clientMemories[client].DangerousItemsContained = memory.DangerousItemsContained + 1;
|
||||
}
|
||||
}
|
||||
|
||||
private void AdjustKarma(Character target, float amount, string debugKarmaChangeReason = "")
|
||||
{
|
||||
if (target == null) { return; }
|
||||
|
||||
+2
-17
@@ -113,22 +113,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
public void CreateEvent(IServerSerializable entity, object[] extraData = null)
|
||||
{
|
||||
if (entity == null || !(entity is Entity))
|
||||
{
|
||||
DebugConsole.ThrowError("Can't create an entity event for " + entity + "!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (((Entity)entity).Removed && !(entity is Level))
|
||||
{
|
||||
DebugConsole.ThrowError("Can't create an entity event for " + entity + " - the entity has been removed.\n"+Environment.StackTrace.CleanupStackTrace());
|
||||
return;
|
||||
}
|
||||
if (((Entity)entity).IdFreed)
|
||||
{
|
||||
DebugConsole.ThrowError("Can't create an entity event for " + entity + " - the ID of the entity has been freed.\n"+Environment.StackTrace.CleanupStackTrace());
|
||||
return;
|
||||
}
|
||||
if (!ValidateEntity(entity)) { return; }
|
||||
|
||||
var newEvent = new ServerEntityEvent(entity, (UInt16)(ID + 1));
|
||||
if (extraData != null) newEvent.SetData(extraData);
|
||||
@@ -201,7 +186,7 @@ namespace Barotrauma.Networking
|
||||
DebugConsole.ThrowError(errorMsg, e);
|
||||
}
|
||||
GameAnalyticsManager.AddErrorEventOnce("ServerEntityEventManager.Read:ReadFailed" + entityName,
|
||||
GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
|
||||
GameAnalyticsManager.ErrorSeverity.Error,
|
||||
"Failed to read server event for entity \"" + entityName + "\"!\n" + e.StackTrace.CleanupStackTrace());
|
||||
}
|
||||
|
||||
|
||||
+5
-7
@@ -129,7 +129,7 @@ namespace Barotrauma.Networking
|
||||
catch (Exception e)
|
||||
{
|
||||
string errorMsg = "Server failed to read an incoming message. {" + e + "}\n" + e.StackTrace.CleanupStackTrace();
|
||||
GameAnalyticsManager.AddErrorEventOnce("LidgrenServerPeer.Update:ClientReadException" + e.TargetSite.ToString(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("LidgrenServerPeer.Update:ClientReadException" + e.TargetSite.ToString(), GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
#else
|
||||
@@ -212,15 +212,13 @@ namespace Barotrauma.Networking
|
||||
|
||||
PendingClient pendingClient = pendingClients.Find(c => (c.Connection is LidgrenConnection l) && l.NetConnection == inc.SenderConnection);
|
||||
|
||||
byte incByte = inc.ReadByte();
|
||||
bool isCompressed = (incByte & (byte)PacketHeader.IsCompressed) != 0;
|
||||
bool isConnectionInitializationStep = (incByte & (byte)PacketHeader.IsConnectionInitializationStep) != 0;
|
||||
PacketHeader packetHeader = (PacketHeader)inc.ReadByte();
|
||||
|
||||
if (isConnectionInitializationStep && pendingClient != null)
|
||||
if (packetHeader.IsConnectionInitializationStep() && pendingClient != null)
|
||||
{
|
||||
ReadConnectionInitializationStep(pendingClient, new ReadWriteMessage(inc.Data, (int)inc.Position, inc.LengthBits, false));
|
||||
}
|
||||
else if (!isConnectionInitializationStep)
|
||||
else if (!packetHeader.IsConnectionInitializationStep())
|
||||
{
|
||||
LidgrenConnection conn = connectedClients.Find(c => (c is LidgrenConnection l) && l.NetConnection == inc.SenderConnection) as LidgrenConnection;
|
||||
if (conn == null)
|
||||
@@ -246,7 +244,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
//DebugConsole.NewMessage(isCompressed + " " + isConnectionInitializationStep + " " + (int)incByte + " " + length);
|
||||
|
||||
IReadMessage msg = new ReadOnlyMessage(inc.Data, isCompressed, inc.PositionInBytes, length, conn);
|
||||
IReadMessage msg = new ReadOnlyMessage(inc.Data, packetHeader.IsCompressed(), inc.PositionInBytes, length, conn);
|
||||
OnMessageReceived?.Invoke(conn, msg);
|
||||
}
|
||||
}
|
||||
|
||||
+13
-18
@@ -102,7 +102,7 @@ namespace Barotrauma.Networking
|
||||
catch (Exception e)
|
||||
{
|
||||
string errorMsg = "Server failed to read an incoming message. {" + e + "}\n" + e.StackTrace.CleanupStackTrace();
|
||||
GameAnalyticsManager.AddErrorEventOnce("SteamP2PServerPeer.Update:ClientReadException" + e.TargetSite.ToString(), GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg);
|
||||
GameAnalyticsManager.AddErrorEventOnce("SteamP2PServerPeer.Update:ClientReadException" + e.TargetSite.ToString(), GameAnalyticsManager.ErrorSeverity.Error, errorMsg);
|
||||
#if DEBUG
|
||||
DebugConsole.ThrowError(errorMsg);
|
||||
#else
|
||||
@@ -125,14 +125,9 @@ namespace Barotrauma.Networking
|
||||
UInt64 senderSteamId = inc.ReadUInt64();
|
||||
UInt64 ownerSteamId = inc.ReadUInt64();
|
||||
|
||||
byte incByte = inc.ReadByte();
|
||||
bool isCompressed = (incByte & (byte)PacketHeader.IsCompressed) != 0;
|
||||
bool isConnectionInitializationStep = (incByte & (byte)PacketHeader.IsConnectionInitializationStep) != 0;
|
||||
bool isDisconnectMessage = (incByte & (byte)PacketHeader.IsDisconnectMessage) != 0;
|
||||
bool isServerMessage = (incByte & (byte)PacketHeader.IsServerMessage) != 0;
|
||||
bool isHeartbeatMessage = (incByte & (byte)PacketHeader.IsHeartbeatMessage) != 0;
|
||||
PacketHeader packetHeader = (PacketHeader)inc.ReadByte();
|
||||
|
||||
if (isServerMessage)
|
||||
if (packetHeader.IsServerMessage())
|
||||
{
|
||||
DebugConsole.ThrowError("Got server message from" + senderSteamId.ToString());
|
||||
return;
|
||||
@@ -160,7 +155,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (isDisconnectMessage)
|
||||
else if (packetHeader.IsDisconnectMessage())
|
||||
{
|
||||
if (pendingClient != null)
|
||||
{
|
||||
@@ -174,12 +169,12 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (isHeartbeatMessage)
|
||||
else if (packetHeader.IsHeartbeatMessage())
|
||||
{
|
||||
//message exists solely as a heartbeat, ignore its contents
|
||||
return;
|
||||
}
|
||||
else if (isConnectionInitializationStep)
|
||||
else if (packetHeader.IsConnectionInitializationStep())
|
||||
{
|
||||
|
||||
if (pendingClient != null)
|
||||
@@ -203,7 +198,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
UInt16 length = inc.ReadUInt16();
|
||||
|
||||
IReadMessage msg = new ReadOnlyMessage(inc.Buffer, isCompressed, inc.BytePosition, length, connectedClient);
|
||||
IReadMessage msg = new ReadOnlyMessage(inc.Buffer, packetHeader.IsCompressed(), inc.BytePosition, length, connectedClient);
|
||||
OnMessageReceived?.Invoke(connectedClient, msg);
|
||||
}
|
||||
}
|
||||
@@ -211,17 +206,17 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (OwnerConnection != null) { (OwnerConnection as SteamP2PConnection).Heartbeat(); }
|
||||
|
||||
if (isDisconnectMessage)
|
||||
if (packetHeader.IsDisconnectMessage())
|
||||
{
|
||||
DebugConsole.ThrowError("Received disconnect message from owner");
|
||||
return;
|
||||
}
|
||||
if (isServerMessage)
|
||||
if (packetHeader.IsServerMessage())
|
||||
{
|
||||
DebugConsole.ThrowError("Received server message from owner");
|
||||
return;
|
||||
}
|
||||
if (isConnectionInitializationStep)
|
||||
if (packetHeader.IsConnectionInitializationStep())
|
||||
{
|
||||
if (OwnerConnection == null)
|
||||
{
|
||||
@@ -236,7 +231,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (isHeartbeatMessage)
|
||||
if (packetHeader.IsHeartbeatMessage())
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -244,7 +239,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
UInt16 length = inc.ReadUInt16();
|
||||
|
||||
IReadMessage msg = new ReadOnlyMessage(inc.Buffer, isCompressed, inc.BytePosition, length, OwnerConnection);
|
||||
IReadMessage msg = new ReadOnlyMessage(inc.Buffer, packetHeader.IsCompressed(), inc.BytePosition, length, OwnerConnection);
|
||||
OnMessageReceived?.Invoke(OwnerConnection, msg);
|
||||
}
|
||||
}
|
||||
@@ -267,7 +262,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
IWriteMessage msgToSend = new WriteOnlyMessage();
|
||||
byte[] msgData = new byte[msg.LengthBytes];
|
||||
byte[] msgData = new byte[16];
|
||||
msg.PrepareForSending(ref msgData, out bool isCompressed, out int length);
|
||||
msgToSend.Write(conn.SteamID);
|
||||
msgToSend.Write((byte)deliveryMethod);
|
||||
|
||||
@@ -52,6 +52,29 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsRespawnPromptPendingForClient(Client c)
|
||||
{
|
||||
if (!UseRespawnPrompt || !(GameMain.GameSession.GameMode is MultiPlayerCampaign campaign)) { return false; }
|
||||
|
||||
if (!c.InGame) { return false; }
|
||||
if (c.SpectateOnly && (GameMain.Server.ServerSettings.AllowSpectating || GameMain.Server.OwnerConnection == c.Connection)) { return false; }
|
||||
if (c.Character != null && !c.Character.IsDead) { return false; }
|
||||
|
||||
var matchingData = campaign.GetClientCharacterData(c);
|
||||
if (matchingData != null && matchingData.HasSpawned)
|
||||
{
|
||||
if (Character.CharacterList.Any(c => c.Info == matchingData.CharacterInfo && !c.IsDead))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!c.WaitForNextRoundRespawn.HasValue)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private List<CharacterInfo> GetBotsToRespawn()
|
||||
{
|
||||
if (GameMain.Server.ServerSettings.BotSpawnMode == BotSpawnMode.Normal)
|
||||
@@ -325,7 +348,7 @@ namespace Barotrauma.Networking
|
||||
c.WaitForNextRoundRespawn = null;
|
||||
|
||||
var matchingData = campaign?.GetClientCharacterData(c);
|
||||
if (matchingData != null && !matchingData.HasSpawned)
|
||||
if (matchingData != null)
|
||||
{
|
||||
c.CharacterInfo = matchingData.CharacterInfo;
|
||||
}
|
||||
@@ -396,6 +419,7 @@ namespace Barotrauma.Networking
|
||||
else
|
||||
{
|
||||
ReduceCharacterSkills(characterInfos[i]);
|
||||
characterInfos[i].RemoveSavedStatValuesOnDeath();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -514,9 +538,9 @@ namespace Barotrauma.Networking
|
||||
if (characterInfo?.Job == null) { return; }
|
||||
foreach (Skill skill in characterInfo.Job.Skills)
|
||||
{
|
||||
var skillPrefab = characterInfo.Job.Prefab.Skills.Find(s => skill.Prefab == s);
|
||||
var skillPrefab = characterInfo.Job.Prefab.Skills.Find(s => skill.Identifier.Equals(s.Identifier, StringComparison.OrdinalIgnoreCase));
|
||||
if (skillPrefab == null) { continue; }
|
||||
skill.Level = MathHelper.Lerp(skill.Level, skillPrefab.LevelRange.X, SkillReductionOnCampaignMidroundRespawn);
|
||||
skill.Level = MathHelper.Lerp(skill.Level, skillPrefab.LevelRange.Start, SkillReductionOnCampaignMidroundRespawn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -532,9 +556,14 @@ namespace Barotrauma.Networking
|
||||
msg.Write((float)(ReturnTime - DateTime.Now).TotalSeconds);
|
||||
break;
|
||||
case State.Waiting:
|
||||
MultiPlayerCampaign campaign = GameMain.GameSession.GameMode as MultiPlayerCampaign;
|
||||
var matchingData = campaign?.GetClientCharacterData(c);
|
||||
bool forceSpawnInMainSub = matchingData != null && !matchingData.HasSpawned;
|
||||
msg.Write((ushort)pendingRespawnCount);
|
||||
msg.Write((ushort)requiredRespawnCount);
|
||||
msg.Write(IsRespawnPromptPendingForClient(c));
|
||||
msg.Write(RespawnCountdownStarted);
|
||||
msg.Write(forceSpawnInMainSub);
|
||||
msg.Write((float)(RespawnTime - DateTime.Now).TotalSeconds);
|
||||
break;
|
||||
case State.Returning:
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Extensions;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
@@ -13,6 +14,21 @@ namespace Barotrauma.Networking
|
||||
public static readonly string ClientPermissionsFile = "Data" + Path.DirectorySeparatorChar + "clientpermissions.xml";
|
||||
public static readonly char SubmarineSeparatorChar = '|';
|
||||
|
||||
public readonly Dictionary<NetFlags, UInt16> LastUpdateIdForFlag = new Dictionary<NetFlags, UInt16>();
|
||||
public UInt16 LastPropertyUpdateId { get; private set; } = 1;
|
||||
|
||||
public void UpdateFlag(NetFlags flag)
|
||||
=> LastUpdateIdForFlag[flag] = (UInt16)(GameMain.NetLobbyScreen.LastUpdateID + 1);
|
||||
|
||||
private bool IsFlagRequired(Client c, NetFlags flag)
|
||||
=> LastUpdateIdForFlag[flag] > c.LastRecvLobbyUpdate;
|
||||
|
||||
public NetFlags GetRequiredFlags(Client c)
|
||||
=> LastUpdateIdForFlag.Keys
|
||||
.Where(k => IsFlagRequired(c, k))
|
||||
.Concat(NetFlags.None.ToEnumerable()) //prevents InvalidOperationException in Aggregate
|
||||
.Aggregate((f1, f2) => f1 | f2);
|
||||
|
||||
partial void InitProjSpecific()
|
||||
{
|
||||
LoadSettings();
|
||||
@@ -31,11 +47,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
public void ServerAdminWrite(IWriteMessage outMsg, Client c)
|
||||
{
|
||||
//outMsg.Write(isPublic);
|
||||
//outMsg.Write(EnableUPnP);
|
||||
//outMsg.WritePadBits();
|
||||
//outMsg.Write((UInt16)QueryPort);
|
||||
|
||||
c.LastSentServerSettingsUpdate = LastPropertyUpdateId;
|
||||
WriteNetProperties(outMsg);
|
||||
WriteMonsterEnabled(outMsg);
|
||||
BanList.ServerAdminWrite(outMsg, c);
|
||||
@@ -44,8 +56,18 @@ namespace Barotrauma.Networking
|
||||
|
||||
public void ServerWrite(IWriteMessage outMsg, Client c)
|
||||
{
|
||||
outMsg.Write(ServerName);
|
||||
outMsg.Write(ServerMessageText);
|
||||
NetFlags requiredFlags = GetRequiredFlags(c);
|
||||
outMsg.Write((byte)requiredFlags);
|
||||
if (requiredFlags.HasFlag(NetFlags.Name))
|
||||
{
|
||||
outMsg.Write(ServerName);
|
||||
}
|
||||
|
||||
if (requiredFlags.HasFlag(NetFlags.Message))
|
||||
{
|
||||
outMsg.Write(ServerMessageText);
|
||||
}
|
||||
outMsg.Write((byte)PlayStyle);
|
||||
outMsg.Write((byte)MaxPlayers);
|
||||
outMsg.Write(HasPassword);
|
||||
outMsg.Write(IsPublic);
|
||||
@@ -53,11 +75,15 @@ namespace Barotrauma.Networking
|
||||
outMsg.WritePadBits();
|
||||
outMsg.WriteRangedInteger(TickRate, 1, 60);
|
||||
|
||||
WriteExtraCargo(outMsg);
|
||||
if (requiredFlags.HasFlag(NetFlags.Properties))
|
||||
{
|
||||
WriteExtraCargo(outMsg);
|
||||
}
|
||||
|
||||
WriteHiddenSubs(outMsg);
|
||||
|
||||
Voting.ServerWrite(outMsg);
|
||||
|
||||
if (c.HasPermission(Networking.ClientPermissions.ManageSettings))
|
||||
if (c.HasPermission(Networking.ClientPermissions.ManageSettings)
|
||||
&& !NetIdUtils.IdMoreRecentOrMatches(c.LastRecvServerSettingsUpdate, LastPropertyUpdateId))
|
||||
{
|
||||
outMsg.Write(true);
|
||||
outMsg.WritePadBits();
|
||||
@@ -82,20 +108,20 @@ namespace Barotrauma.Networking
|
||||
if (flags.HasFlag(NetFlags.Name))
|
||||
{
|
||||
string serverName = incMsg.ReadString();
|
||||
if (ServerName != serverName) changed = true;
|
||||
if (ServerName != serverName) { changed = true; }
|
||||
ServerName = serverName;
|
||||
}
|
||||
|
||||
if (flags.HasFlag(NetFlags.Message))
|
||||
{
|
||||
string serverMessageText = incMsg.ReadString();
|
||||
if (ServerMessageText != serverMessageText) changed = true;
|
||||
if (ServerMessageText != serverMessageText) { changed = true; }
|
||||
ServerMessageText = serverMessageText;
|
||||
}
|
||||
|
||||
if (flags.HasFlag(NetFlags.Properties))
|
||||
{
|
||||
changed |= ReadExtraCargo(incMsg);
|
||||
bool propertiesChanged = ReadExtraCargo(incMsg);
|
||||
|
||||
UInt32 count = incMsg.ReadUInt32();
|
||||
|
||||
@@ -111,7 +137,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
GameServer.Log(GameServer.ClientLogName(c) + " changed " + netProperties[key].Name + " to " + netProperties[key].Value.ToString(), ServerLog.MessageType.ServerMessage);
|
||||
}
|
||||
changed = true;
|
||||
propertiesChanged = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -121,12 +147,25 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
bool changedMonsterSettings = incMsg.ReadBoolean(); incMsg.ReadPadBits();
|
||||
changed |= changedMonsterSettings;
|
||||
if (changedMonsterSettings) ReadMonsterEnabled(incMsg);
|
||||
changed |= BanList.ServerAdminRead(incMsg, c);
|
||||
changed |= Whitelist.ServerAdminRead(incMsg, c);
|
||||
propertiesChanged |= changedMonsterSettings;
|
||||
if (changedMonsterSettings) { ReadMonsterEnabled(incMsg); }
|
||||
propertiesChanged |= BanList.ServerAdminRead(incMsg, c);
|
||||
propertiesChanged |= Whitelist.ServerAdminRead(incMsg, c);
|
||||
|
||||
if (propertiesChanged)
|
||||
{
|
||||
UpdateFlag(NetFlags.Properties);
|
||||
LastPropertyUpdateId = (UInt16)(GameMain.NetLobbyScreen.LastUpdateID + 1);
|
||||
}
|
||||
changed |= propertiesChanged;
|
||||
}
|
||||
|
||||
if (flags.HasFlag(NetFlags.HiddenSubs))
|
||||
{
|
||||
ReadHiddenSubs(incMsg);
|
||||
changed |= true;
|
||||
}
|
||||
|
||||
if (flags.HasFlag(NetFlags.Misc))
|
||||
{
|
||||
int orBits = incMsg.ReadRangedInteger(0, (int)Barotrauma.MissionType.All) & (int)Barotrauma.MissionType.All;
|
||||
@@ -166,12 +205,14 @@ namespace Barotrauma.Networking
|
||||
MaxMissionCount = MathHelper.Clamp(maxMissionCount, CampaignSettings.MinMissionCountLimit, CampaignSettings.MaxMissionCountLimit);
|
||||
|
||||
changed |= true;
|
||||
UpdateFlag(NetFlags.Misc);
|
||||
}
|
||||
|
||||
if (flags.HasFlag(NetFlags.LevelSeed))
|
||||
{
|
||||
GameMain.NetLobbyScreen.LevelSeed = incMsg.ReadString();
|
||||
changed |= true;
|
||||
UpdateFlag(NetFlags.LevelSeed);
|
||||
}
|
||||
|
||||
if (changed)
|
||||
@@ -205,6 +246,8 @@ namespace Barotrauma.Networking
|
||||
|
||||
doc.Root.SetAttributeValue("ServerMessage", ServerMessageText);
|
||||
|
||||
doc.Root.SetAttributeValue("HiddenSubs", string.Join(",", HiddenSubs));
|
||||
|
||||
doc.Root.SetAttributeValue("AllowedRandomMissionTypes", string.Join(",", AllowedRandomMissionTypes));
|
||||
doc.Root.SetAttributeValue("AllowedClientNameChars", string.Join(",", AllowedClientNameChars.Select(c => c.First + "-" + c.Second)));
|
||||
|
||||
@@ -243,6 +286,11 @@ namespace Barotrauma.Networking
|
||||
|
||||
SerializableProperties = SerializableProperty.DeserializeProperties(this, doc.Root);
|
||||
|
||||
if (string.IsNullOrEmpty(doc.Root.GetAttributeString("losmode", "")))
|
||||
{
|
||||
LosMode = GameMain.Config.LosMode;
|
||||
}
|
||||
|
||||
AutoRestart = doc.Root.GetAttributeBool("autorestart", false);
|
||||
|
||||
Voting.AllowSubVoting = SubSelectionMode == SelectionMode.Vote;
|
||||
@@ -253,6 +301,10 @@ namespace Barotrauma.Networking
|
||||
|
||||
GameMain.NetLobbyScreen.SetTraitorsEnabled(traitorsEnabled);
|
||||
|
||||
HiddenSubs.UnionWith(doc.Root.GetAttributeStringArray("HiddenSubs", Array.Empty<string>()));
|
||||
|
||||
SelectedSubmarine = SelectNonHiddenSubmarine(SelectedSubmarine);
|
||||
|
||||
string[] defaultAllowedClientNameChars =
|
||||
new string[] {
|
||||
"32-33",
|
||||
@@ -327,7 +379,6 @@ namespace Barotrauma.Networking
|
||||
|
||||
GameMain.NetLobbyScreen.SetBotSpawnMode(BotSpawnMode);
|
||||
GameMain.NetLobbyScreen.SetBotCount(BotCount);
|
||||
GameMain.NetLobbyScreen.SetMaxMissionCount(MaxMissionCount);
|
||||
|
||||
List<string> monsterNames = CharacterPrefab.Prefabs.Select(p => p.Identifier).ToList();
|
||||
MonsterEnabled = new Dictionary<string, bool>();
|
||||
@@ -337,6 +388,27 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
public string SelectNonHiddenSubmarine(string current = null)
|
||||
{
|
||||
current ??= GameMain.NetLobbyScreen.SelectedSub.Name;
|
||||
if (HiddenSubs.Contains(current))
|
||||
{
|
||||
var candidates
|
||||
= GameMain.NetLobbyScreen.GetSubList().Where(s => !HiddenSubs.Contains(s.Name)).ToArray();
|
||||
if (candidates.Any())
|
||||
{
|
||||
GameMain.NetLobbyScreen.SelectedSub = candidates.GetRandom(Rand.RandSync.Unsynced);
|
||||
return GameMain.NetLobbyScreen.SelectedSub.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
HiddenSubs.Remove(current);
|
||||
return current;
|
||||
}
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
public void LoadClientPermissions()
|
||||
{
|
||||
ClientPermissions.Clear();
|
||||
|
||||
@@ -30,10 +30,9 @@ namespace Barotrauma
|
||||
|
||||
public static SubmarineVote SubVote;
|
||||
|
||||
private void StartSubmarineVote(IReadMessage inc, VoteType voteType, Client sender)
|
||||
private void StartSubmarineVote(SubmarineInfo subInfo, VoteType voteType, Client sender)
|
||||
{
|
||||
string subName = inc.ReadString();
|
||||
SubVote.Sub = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == subName);
|
||||
SubVote.Sub = subInfo;
|
||||
SubVote.DeliveryFee = voteType == VoteType.SwitchSub ? GameMain.GameSession.Map.DistanceToClosestLocationWithOutpost(GameMain.GameSession.Map.CurrentLocation, out Location endLocation) : 0;
|
||||
SubVote.VoteType = voteType;
|
||||
SubVote.State = VoteState.Started;
|
||||
@@ -130,7 +129,12 @@ namespace Barotrauma
|
||||
bool startVote = inc.ReadBoolean();
|
||||
if (startVote)
|
||||
{
|
||||
StartSubmarineVote(inc, voteType, sender);
|
||||
string subName = inc.ReadString();
|
||||
SubmarineInfo subInfo = SubmarineInfo.SavedSubmarines.FirstOrDefault(s => s.Name == subName);
|
||||
if (GameMain.GameSession?.Campaign is MultiPlayerCampaign campaign && campaign.CanPurchaseSub(subInfo))
|
||||
{
|
||||
StartSubmarineVote(subInfo, voteType, sender);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -155,23 +159,23 @@ namespace Barotrauma
|
||||
msg.Write(allowSubVoting);
|
||||
if (allowSubVoting)
|
||||
{
|
||||
List<Pair<object, int>> voteList = GetVoteList(VoteType.Sub, GameMain.Server.ConnectedClients);
|
||||
IReadOnlyDictionary<SubmarineInfo, int> voteList = GetVoteCounts<SubmarineInfo>(VoteType.Sub, GameMain.Server.ConnectedClients);
|
||||
msg.Write((byte)voteList.Count);
|
||||
foreach (Pair<object, int> vote in voteList)
|
||||
foreach (KeyValuePair<SubmarineInfo, int> vote in voteList)
|
||||
{
|
||||
msg.Write((byte)vote.Second);
|
||||
msg.Write(((SubmarineInfo)vote.First).Name);
|
||||
msg.Write((byte)vote.Value);
|
||||
msg.Write(vote.Key.Name);
|
||||
}
|
||||
}
|
||||
msg.Write(AllowModeVoting);
|
||||
if (allowModeVoting)
|
||||
{
|
||||
List<Pair<object, int>> voteList = GetVoteList(VoteType.Mode, GameMain.Server.ConnectedClients);
|
||||
IReadOnlyDictionary<GameModePreset, int> voteList = GetVoteCounts<GameModePreset>(VoteType.Mode, GameMain.Server.ConnectedClients);
|
||||
msg.Write((byte)voteList.Count);
|
||||
foreach (Pair<object, int> vote in voteList)
|
||||
foreach (KeyValuePair<GameModePreset, int> vote in voteList)
|
||||
{
|
||||
msg.Write((byte)vote.Second);
|
||||
msg.Write(((GameModePreset)vote.First).Identifier);
|
||||
msg.Write((byte)vote.Value);
|
||||
msg.Write(vote.Key.Identifier);
|
||||
}
|
||||
}
|
||||
msg.Write(AllowEndVoting);
|
||||
|
||||
@@ -69,6 +69,8 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
GameServer.Log("Saving whitelist", ServerLog.MessageType.ServerMessage);
|
||||
|
||||
GameMain.Server?.ServerSettings?.UpdateFlag(ServerSettings.NetFlags.Properties);
|
||||
|
||||
List<string> lines = new List<string>();
|
||||
|
||||
if (Enabled)
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#region Using Statements
|
||||
|
||||
using Barotrauma.Steam;
|
||||
using GameAnalyticsSDK.Net;
|
||||
using System;
|
||||
using Barotrauma.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
#if LINUX
|
||||
using System.Runtime.InteropServices;
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -42,11 +42,11 @@ namespace Barotrauma
|
||||
#endif
|
||||
Console.WriteLine("Barotrauma Dedicated Server " + GameMain.Version +
|
||||
" (" + AssemblyInfo.BuildString + ", branch " + AssemblyInfo.GitBranch + ", revision " + AssemblyInfo.GitRevision + ")");
|
||||
if(Console.IsOutputRedirected)
|
||||
if (Console.IsOutputRedirected)
|
||||
{
|
||||
Console.WriteLine("Output redirection detected; colored text and command input will be disabled.");
|
||||
}
|
||||
if(Console.IsInputRedirected)
|
||||
if (Console.IsInputRedirected)
|
||||
{
|
||||
Console.WriteLine("Redirected input is detected but is not supported by this application. Input will be ignored.");
|
||||
}
|
||||
@@ -60,7 +60,7 @@ namespace Barotrauma
|
||||
Game = new GameMain(args);
|
||||
|
||||
Game.Run();
|
||||
if (GameSettings.SendUserStatistics) { GameAnalytics.OnQuit(); }
|
||||
if (GameAnalyticsManager.SendUserStatistics) { GameAnalyticsManager.ShutDown(); }
|
||||
SteamManager.ShutDown();
|
||||
}
|
||||
|
||||
@@ -156,11 +156,18 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
if (GameAnalyticsManager.SendUserStatistics)
|
||||
{
|
||||
//send crash report before appending debug console messages (which may contain non-anonymous information)
|
||||
GameAnalyticsManager.AddErrorEvent(GameAnalyticsManager.ErrorSeverity.Critical, sb.ToString());
|
||||
GameAnalyticsManager.ShutDown();
|
||||
}
|
||||
|
||||
sb.AppendLine("Last debug messages:");
|
||||
DebugConsole.Clear();
|
||||
for (int i = DebugConsole.Messages.Count - 1; i > 0 && i > DebugConsole.Messages.Count - 15; i-- )
|
||||
for (int i = DebugConsole.Messages.Count - 1; i > 0 && i > DebugConsole.Messages.Count - 15; i--)
|
||||
{
|
||||
sb.AppendLine(" "+DebugConsole.Messages[i].Time+" - "+DebugConsole.Messages[i].Text);
|
||||
sb.AppendLine(" " + DebugConsole.Messages[i].Time + " - " + DebugConsole.Messages[i].Text);
|
||||
}
|
||||
|
||||
string crashReport = sb.ToString();
|
||||
@@ -171,12 +178,12 @@ namespace Barotrauma
|
||||
}
|
||||
Console.Write(crashReport);
|
||||
|
||||
File.WriteAllText(filePath,sb.ToString());
|
||||
File.WriteAllText(filePath, sb.ToString());
|
||||
|
||||
if (GameSettings.SendUserStatistics)
|
||||
if (GameSettings.SaveDebugConsoleLogs || GameSettings.VerboseLogging) { DebugConsole.SaveLogs(); }
|
||||
|
||||
if (GameAnalyticsManager.SendUserStatistics)
|
||||
{
|
||||
GameAnalytics.AddErrorEvent(EGAErrorSeverity.Critical, crashReport);
|
||||
GameAnalytics.OnQuit();
|
||||
Console.Write("A crash report (\"servercrashreport.log\") was saved in the root folder of the game and sent to the developers.");
|
||||
}
|
||||
else
|
||||
|
||||
@@ -32,6 +32,7 @@ namespace Barotrauma
|
||||
set { selectedShuttle = value; lastUpdateID++; }
|
||||
}
|
||||
|
||||
[Obsolete("TODO: this list shouldn't exist, the client should just use the visible subs list instead")]
|
||||
public List<SubmarineInfo> CampaignSubmarines
|
||||
{
|
||||
get
|
||||
@@ -51,42 +52,6 @@ namespace Barotrauma
|
||||
|
||||
private List<SubmarineInfo> campaignSubmarines;
|
||||
|
||||
public void AddCampaignSubmarine(SubmarineInfo sub)
|
||||
{
|
||||
if (!campaignSubmarines.Contains(sub))
|
||||
{
|
||||
campaignSubmarines.Add(sub);
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lastUpdateID++;
|
||||
if (GameMain.NetworkMember?.ServerSettings != null)
|
||||
{
|
||||
GameMain.NetworkMember.ServerSettings.ServerDetailsChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveCampaignSubmarine(SubmarineInfo sub)
|
||||
{
|
||||
if (campaignSubmarines.Contains(sub))
|
||||
{
|
||||
campaignSubmarines.Remove(sub);
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lastUpdateID++;
|
||||
if (GameMain.NetworkMember?.ServerSettings != null)
|
||||
{
|
||||
GameMain.NetworkMember.ServerSettings.ServerDetailsChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
public GameModePreset[] GameModes { get; }
|
||||
|
||||
private int selectedModeIndex;
|
||||
@@ -212,10 +177,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
private List<SubmarineInfo> subs;
|
||||
public List<SubmarineInfo> GetSubList()
|
||||
{
|
||||
return subs;
|
||||
}
|
||||
public IReadOnlyList<SubmarineInfo> GetSubList() => subs;
|
||||
|
||||
public void AddSub(SubmarineInfo sub)
|
||||
{
|
||||
@@ -276,6 +238,8 @@ namespace Barotrauma
|
||||
var allowedGameModes = Array.FindAll(GameModes, m => !m.IsSinglePlayer && m != GameModePreset.MultiPlayerCampaign);
|
||||
SelectedModeIdentifier = allowedGameModes[Rand.Range(0, allowedGameModes.Length)].Identifier;
|
||||
}
|
||||
|
||||
GameMain.Server.ServerSettings.SelectNonHiddenSubmarine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user