v0.14.6.0

This commit is contained in:
Joonas Rikkonen
2021-06-17 17:54:52 +03:00
parent 3f324b14e8
commit c27e2ea5ab
348 changed files with 13156 additions and 4266 deletions
@@ -22,80 +22,23 @@ namespace Barotrauma.Networking
int? wallSectionIndex = null;
if (type == ChatMessageType.Order)
{
int orderIndex = msg.ReadByte();
orderTargetCharacter = Entity.FindEntityByID(msg.ReadUInt16()) as Character;
orderTargetEntity = Entity.FindEntityByID(msg.ReadUInt16()) as Entity;
Order orderPrefab = null;
int? orderOptionIndex = null;
string orderOption = null;
// The option of a Dismiss order is written differently so we know what order we target
// now that the game supports multiple current orders simultaneously
if (orderIndex >= 0 && orderIndex < Order.PrefabList.Count)
var orderMessageInfo = OrderChatMessage.ReadOrder(msg);
if (orderMessageInfo.OrderIndex < 0 || orderMessageInfo.OrderIndex >= Order.PrefabList.Count)
{
orderPrefab = Order.PrefabList[orderIndex];
if (orderPrefab.Identifier != "dismissed")
{
orderOptionIndex = msg.ReadByte();
}
// Does the dismiss order have a specified target?
else if(msg.ReadBoolean())
{
int identifierCount = msg.ReadByte();
if (identifierCount > 0)
{
int dismissedOrderIndex = msg.ReadByte();
Order dismissedOrderPrefab = null;
if (dismissedOrderIndex >= 0 && dismissedOrderIndex < Order.PrefabList.Count)
{
dismissedOrderPrefab = Order.PrefabList[dismissedOrderIndex];
orderOption = dismissedOrderPrefab.Identifier;
}
if (identifierCount > 1)
{
int dismissedOrderOptionIndex = msg.ReadByte();
if (dismissedOrderPrefab != null)
{
var options = dismissedOrderPrefab.Options;
if (options != null && dismissedOrderOptionIndex >= 0 && dismissedOrderOptionIndex < options.Length)
{
orderOption += $".{options[dismissedOrderOptionIndex]}";
}
}
}
}
}
}
else
{
orderOptionIndex = msg.ReadByte();
}
int orderPriority = msg.ReadByte();
orderTargetType = (Order.OrderTargetType)msg.ReadByte();
if (msg.ReadBoolean())
{
var x = msg.ReadSingle();
var y = msg.ReadSingle();
var hull = Entity.FindEntityByID(msg.ReadUInt16()) as Hull;
orderTargetPosition = new OrderTarget(new Vector2(x, y), hull, true);
}
else if (orderTargetType == Order.OrderTargetType.WallSection)
{
wallSectionIndex = msg.ReadByte();
}
if (orderIndex < 0 || orderIndex >= Order.PrefabList.Count)
{
DebugConsole.ThrowError($"Invalid order message from client \"{c.Name}\" - order index out of bounds ({orderIndex}).");
DebugConsole.ThrowError($"Invalid order message from client \"{c.Name}\" - order index out of bounds ({orderMessageInfo.OrderIndex}).");
if (NetIdUtils.IdMoreRecent(ID, c.LastSentChatMsgID)) { c.LastSentChatMsgID = ID; }
return;
}
orderPrefab ??= Order.PrefabList[orderIndex];
orderOption ??= orderOptionIndex == null || orderOptionIndex < 0 || orderOptionIndex >= orderPrefab.Options.Length ? "" : orderPrefab.Options[orderOptionIndex.Value];
orderMsg = new OrderChatMessage(orderPrefab, orderOption, orderPriority, orderTargetPosition ?? orderTargetEntity as ISpatialEntity, orderTargetCharacter, c.Character)
orderTargetCharacter = orderMessageInfo.TargetCharacter;
orderTargetEntity = orderMessageInfo.TargetEntity;
orderTargetPosition = orderMessageInfo.TargetPosition;
orderTargetType = orderMessageInfo.TargetType;
wallSectionIndex = orderMessageInfo.WallSectionIndex;
var orderPrefab = orderMessageInfo.OrderPrefab ?? Order.PrefabList[orderMessageInfo.OrderIndex];
string orderOption = orderMessageInfo.OrderOption ??
(orderMessageInfo.OrderOptionIndex == null || orderMessageInfo.OrderOptionIndex < 0 || orderMessageInfo.OrderOptionIndex >= orderPrefab.Options.Length ?
"" : orderPrefab.Options[orderMessageInfo.OrderOptionIndex.Value]);
orderMsg = new OrderChatMessage(orderPrefab, orderOption, orderMessageInfo.Priority, orderTargetPosition ?? orderTargetEntity as ISpatialEntity, orderTargetCharacter, c.Character)
{
WallSectionIndex = wallSectionIndex
};
@@ -176,46 +119,49 @@ namespace Barotrauma.Networking
if (type == ChatMessageType.Order)
{
if (c.Character == null || c.Character.SpeechImpediment >= 100.0f || c.Character.IsDead) { return; }
Order order = null;
if (orderMsg.Order.IsReport)
{
HumanAIController.ReportProblem(orderMsg.Sender, orderMsg.Order);
}
else if (orderTargetCharacter != null && !orderMsg.Order.TargetAllCharacters)
Order order = orderTargetType switch
{
switch (orderTargetType)
Order.OrderTargetType.Entity =>
new Order(orderMsg.Order, orderTargetEntity, orderMsg.Order?.GetTargetItemComponent(orderTargetEntity as Item), orderGiver: orderMsg.Sender),
Order.OrderTargetType.Position =>
new Order(orderMsg.Order, orderTargetPosition, orderGiver: orderMsg.Sender),
Order.OrderTargetType.WallSection when orderTargetEntity is Structure s && wallSectionIndex.HasValue =>
new Order(orderMsg.Order, s, wallSectionIndex, orderGiver: orderMsg.Sender),
_ => throw new NotImplementedException()
};
if (order != null)
{
if (order.TargetAllCharacters)
{
case Order.OrderTargetType.Entity:
order = new Order(orderMsg.Order.Prefab, orderTargetEntity, orderMsg.Order.Prefab?.GetTargetItemComponent(orderTargetEntity as Item), orderGiver: orderMsg.Sender);
break;
case Order.OrderTargetType.Position:
order = new Order(orderMsg.Order.Prefab, orderTargetPosition, orderGiver: orderMsg.Sender);
break;
if (order.IsIgnoreOrder)
{
switch (orderTargetType)
{
case Order.OrderTargetType.Entity:
if (!(orderTargetEntity is IIgnorable ignorableEntity)) { break; }
ignorableEntity.OrderedToBeIgnored = order.Identifier == "ignorethis";
break;
case Order.OrderTargetType.Position:
throw new NotImplementedException();
case Order.OrderTargetType.WallSection:
if (!wallSectionIndex.HasValue) { break; }
if (!(orderTargetEntity is Structure s)) { break; }
if (!(s.GetSection(wallSectionIndex.Value) is IIgnorable ignorableWall)) { break; }
ignorableWall.OrderedToBeIgnored = order.Identifier == "ignorethis";
break;
}
}
GameMain.GameSession?.CrewManager?.AddOrder(order, order.IsIgnoreOrder ? (float?)null : order.FadeOutTime);
}
if (order != null)
else if (orderTargetCharacter != null)
{
orderTargetCharacter.SetOrder(order, orderMsg.OrderOption, orderMsg.OrderPriority, orderMsg.Sender);
}
}
else if (orderMsg.Order.IsIgnoreOrder)
{
switch (orderTargetType)
{
case Order.OrderTargetType.Entity:
if (orderTargetEntity is IIgnorable ignorableEntity)
{
ignorableEntity.OrderedToBeIgnored = orderMsg.Order.Identifier == "ignorethis";
}
break;
case Order.OrderTargetType.WallSection:
if (!wallSectionIndex.HasValue) { break; }
if (orderTargetEntity is Structure s && s.GetSection(wallSectionIndex.Value) is IIgnorable ignorableWall)
{
ignorableWall.OrderedToBeIgnored = orderMsg.Order.Identifier == "ignorethis";
}
break;
}
}
GameMain.Server.SendOrderChatMessage(orderMsg);
}
else
@@ -378,7 +378,7 @@ namespace Barotrauma.Networking
if (gameStarted)
{
if (respawnManager != null) { respawnManager.Update(deltaTime); }
respawnManager?.Update(deltaTime);
entityEventManager.Update(connectedClients);
@@ -406,10 +406,7 @@ namespace Barotrauma.Networking
}
}
if (TraitorManager != null)
{
TraitorManager.Update(deltaTime);
}
TraitorManager?.Update(deltaTime);
if (serverSettings.Voting.VoteRunning)
{
@@ -433,7 +430,7 @@ namespace Barotrauma.Networking
connectedClients.All(c => c.Character == null || c.Character.IsDead || c.Character.IsIncapacitated);
bool subAtLevelEnd = false;
if (Submarine.MainSub != null && Submarine.MainSubs[1] == null)
if (Submarine.MainSub != null && !(GameMain.GameSession.GameMode is PvPMode))
{
if (Level.Loaded?.EndOutpost != null)
{
@@ -488,8 +485,10 @@ namespace Barotrauma.Networking
}
else if (isCrewDead && (GameMain.GameSession?.GameMode is CampaignMode))
{
#if !DEBUG
endRoundDelay = 1.0f;
endRoundTimer += deltaTime;
#endif
}
else
{
@@ -537,7 +536,8 @@ namespace Barotrauma.Networking
initiatedStartGame = false;
}
}
else if (Screen.Selected == GameMain.NetLobbyScreen && !gameStarted && !initiatedStartGame)
else if (Screen.Selected == GameMain.NetLobbyScreen && !gameStarted && !initiatedStartGame &&
(GameMain.NetLobbyScreen.SelectedMode != GameModePreset.MultiPlayerCampaign || GameMain.GameSession?.GameMode is MultiPlayerCampaign))
{
if (serverSettings.AutoRestart)
{
@@ -1207,6 +1207,7 @@ namespace Barotrauma.Networking
mpCampaign.ServerReadCrew(inc, sender);
}
}
private void ReadReadyToSpawnMessage(IReadMessage inc, Client sender)
{
sender.SpectateOnly = inc.ReadBoolean() && (serverSettings.AllowSpectating || sender.Connection == OwnerConnection);
@@ -1315,6 +1316,12 @@ namespace Barotrauma.Networking
if (gameStarted)
{
Log("Client \"" + GameServer.ClientLogName(sender) + "\" ended the round.", ServerLog.MessageType.ServerMessage);
if (mpCampaign != null && Level.IsLoadedOutpost)
{
mpCampaign.SaveInventories();
GameMain.GameSession.SubmarineInfo = new SubmarineInfo(GameMain.GameSession.Submarine);
SaveUtil.SaveGame(GameMain.GameSession.SavePath);
}
EndGame();
}
}
@@ -1492,7 +1499,6 @@ namespace Barotrauma.Networking
inc.ReadPadBits();
}
private void ClientWrite(Client c)
{
if (gameStarted && c.InGame)
@@ -1893,6 +1899,7 @@ namespace Barotrauma.Networking
}
outmsg.Write(serverSettings.RadiationEnabled);
outmsg.Write((byte)serverSettings.MaxMissionCount);
}
else
{
@@ -2251,10 +2258,6 @@ namespace Barotrauma.Networking
{
client.CharacterInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, client.Name);
}
else
{
client.CharacterInfo.ClearCurrentOrders();
}
characterInfos.Add(client.CharacterInfo);
if (client.CharacterInfo.Job == null || client.CharacterInfo.Job.Prefab != client.AssignedJob.First)
{
@@ -2340,7 +2343,8 @@ namespace Barotrauma.Networking
else
{
characterData.SpawnInventoryItems(spawnedCharacter, spawnedCharacter.Inventory);
characterData.ApplyHealthData(spawnedCharacter.Info, spawnedCharacter);
characterData.ApplyHealthData(spawnedCharacter);
characterData.ApplyOrderData(spawnedCharacter);
spawnedCharacter.GiveIdCardTags(mainSubWaypoints[i]);
characterData.HasSpawned = true;
}
@@ -2362,7 +2366,7 @@ namespace Barotrauma.Networking
if (hadBots)
{
//loaded existing bots -> init them
crewManager?.InitRound();
crewManager.InitRound();
}
else
{
@@ -2372,6 +2376,7 @@ namespace Barotrauma.Networking
}
campaign?.LoadPets();
crewManager?.LoadActiveOrders();
foreach (Submarine sub in Submarine.MainSubs)
{
@@ -2516,6 +2521,8 @@ namespace Barotrauma.Networking
{
mission.ServerWriteInitial(msg, client);
}
msg.Write(GameMain.GameSession.CrewManager != null);
GameMain.GameSession.CrewManager?.ServerWriteActiveOrders(msg);
}
public void EndGame(CampaignMode.TransitionType transitionType = CampaignMode.TransitionType.None)
@@ -3274,7 +3281,6 @@ namespace Barotrauma.Networking
if (voteType != VoteType.PurchaseSub)
{
SubmarineInfo newSub = GameMain.GameSession.SwitchSubmarine(targetSubmarine, deliveryFee);
GameMain.GameSession.Campaign.UpgradeManager.RefundResetAndReload(newSub, true);
}
serverSettings.Voting.StopSubmarineVote(true);
@@ -3314,7 +3320,6 @@ namespace Barotrauma.Networking
serverSettings.SaveClientPermissions();
}
private IEnumerable<object> SendClientPermissionsAfterClientListSynced(Client recipient, Client client)
{
DateTime timeOut = DateTime.Now + new TimeSpan(0, 0, 10);
@@ -3331,7 +3336,6 @@ namespace Barotrauma.Networking
yield return CoroutineStatus.Success;
}
private void SendClientPermissions(Client recipient, Client client)
{
if (recipient?.Connection == null) { return; }
@@ -10,6 +10,11 @@ namespace Barotrauma.Networking
{
private DateTime despawnTime;
private float shuttleEmptyTimer;
private int pendingRespawnCount, requiredRespawnCount;
private int prevPendingRespawnCount, prevRequiredRespawnCount;
private IEnumerable<Client> GetClientsToRespawn()
{
MultiPlayerCampaign campaign = GameMain.GameSession.GameMode as MultiPlayerCampaign;
@@ -95,10 +100,19 @@ namespace Barotrauma.Networking
RespawnShuttle.Velocity = Vector2.Zero;
}
int clientsToRespawn = GetClientsToRespawn().Count();
pendingRespawnCount = GetClientsToRespawn().Count();
requiredRespawnCount = (int)Math.Max((float)GameMain.Server.ConnectedClients.Count * GameMain.Server.ServerSettings.MinRespawnRatio, 1.0f);
if (pendingRespawnCount != prevPendingRespawnCount ||
requiredRespawnCount != prevRequiredRespawnCount)
{
prevPendingRespawnCount = pendingRespawnCount;
prevRequiredRespawnCount = requiredRespawnCount;
GameMain.Server.CreateEntityEvent(this);
}
if (RespawnCountdownStarted)
{
if (clientsToRespawn == 0)
if (pendingRespawnCount == 0)
{
RespawnCountdownStarted = false;
GameMain.Server.CreateEntityEvent(this);
@@ -106,7 +120,7 @@ namespace Barotrauma.Networking
}
else
{
bool shouldStartCountdown = ShouldStartRespawnCountdown(clientsToRespawn);
bool shouldStartCountdown = ShouldStartRespawnCountdown(pendingRespawnCount);
if (shouldStartCountdown)
{
RespawnCountdownStarted = true;
@@ -167,8 +181,14 @@ namespace Barotrauma.Networking
}
}
partial void UpdateReturningProjSpecific()
partial void UpdateReturningProjSpecific(float deltaTime)
{
//speed up despawning if there's no-one inside the shuttle
if (despawnTime > DateTime.Now + new TimeSpan(0, 0, seconds: 30) && CheckShuttleEmpty(deltaTime))
{
despawnTime = DateTime.Now + new TimeSpan(0, 0, seconds: 30);
}
foreach (Door door in shuttleDoors)
{
if (door.IsOpen) door.TrySetState(false, false, true);
@@ -214,7 +234,7 @@ namespace Barotrauma.Networking
if (!ReturnCountdownStarted)
{
//if there are no living chracters inside, transporting can be stopped immediately
if (!Character.CharacterList.Any(c => c.Submarine == RespawnShuttle && !c.IsDead))
if (CheckShuttleEmpty(deltaTime))
{
ReturnTime = DateTime.Now;
ReturnCountdownStarted = true;
@@ -232,6 +252,10 @@ namespace Barotrauma.Networking
GameMain.Server.CreateEntityEvent(this);
}
}
else if (CheckShuttleEmpty(deltaTime))
{
ReturnTime = DateTime.Now;
}
if (DateTime.Now > ReturnTime)
{
@@ -245,6 +269,19 @@ namespace Barotrauma.Networking
}
}
private bool CheckShuttleEmpty(float deltaTime)
{
if (!Character.CharacterList.Any(c => c.Submarine == RespawnShuttle && !c.IsDead))
{
shuttleEmptyTimer += deltaTime;
}
else
{
shuttleEmptyTimer = 0.0f;
}
return shuttleEmptyTimer > 1.0f;
}
partial void RespawnCharactersProjSpecific(Vector2? shuttlePos)
{
var respawnSub = RespawnShuttle ?? Submarine.MainSub;
@@ -394,7 +431,7 @@ namespace Barotrauma.Networking
else
{
characterData.SpawnInventoryItems(character, character.Inventory);
characterData.ApplyHealthData(character.Info, character);
characterData.ApplyHealthData(character);
character.GiveIdCardTags(mainSubSpawnPoints[i]);
characterData.HasSpawned = true;
}
@@ -427,6 +464,8 @@ namespace Barotrauma.Networking
msg.Write((float)(ReturnTime - DateTime.Now).TotalSeconds);
break;
case State.Waiting:
msg.Write((ushort)pendingRespawnCount);
msg.Write((ushort)requiredRespawnCount);
msg.Write(RespawnCountdownStarted);
msg.Write((float)(RespawnTime - DateTime.Now).TotalSeconds);
break;
@@ -162,6 +162,11 @@ namespace Barotrauma.Networking
RadiationEnabled = incMsg.ReadBoolean();
int maxMissionCount = MaxMissionCount + incMsg.ReadByte() - 1;
if (maxMissionCount < CampaignSettings.MinMissionCountLimit) maxMissionCount = CampaignSettings.MaxMissionCountLimit;
if (maxMissionCount > CampaignSettings.MaxMissionCountLimit) maxMissionCount = CampaignSettings.MinMissionCountLimit;
MaxMissionCount = maxMissionCount;
changed |= true;
}
@@ -306,7 +311,8 @@ namespace Barotrauma.Networking
{
if (Enum.TryParse(missionTypeName, out MissionType missionType))
{
if (missionType == Barotrauma.MissionType.None) continue;
if (missionType == Barotrauma.MissionType.None) { continue; }
if (MissionPrefab.HiddenMissionClasses.Contains(missionType)) { continue; }
AllowedRandomMissionTypes.Add(missionType);
}
}
@@ -323,6 +329,7 @@ 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>();