Unstable v0.1300.0.0 (February 19th 2021)
This commit is contained in:
@@ -1,9 +1,27 @@
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class CharacterInfo
|
||||
{
|
||||
private readonly Dictionary<string, float> prevSentSkill = new Dictionary<string, float>();
|
||||
|
||||
partial void OnSkillChanged(string skillIdentifier, float prevLevel, float newLevel, Vector2 textPopupPos)
|
||||
{
|
||||
if (!prevSentSkill.ContainsKey(skillIdentifier))
|
||||
{
|
||||
prevSentSkill[skillIdentifier] = prevLevel;
|
||||
}
|
||||
if (Math.Abs(prevSentSkill[skillIdentifier] - newLevel) > 0.01f)
|
||||
{
|
||||
GameMain.NetworkMember.CreateEntityEvent(Character, new object[] { NetEntityEvent.Type.UpdateSkills });
|
||||
prevSentSkill[skillIdentifier] = newLevel;
|
||||
}
|
||||
}
|
||||
|
||||
public void ServerWrite(IWriteMessage msg)
|
||||
{
|
||||
msg.Write(ID);
|
||||
|
||||
@@ -26,6 +26,11 @@ namespace Barotrauma
|
||||
Vector2 comparePosition = recipient.SpectatePos == null ? recipient.Character.WorldPosition : recipient.SpectatePos.Value;
|
||||
|
||||
float distance = Vector2.Distance(comparePosition, WorldPosition);
|
||||
if (recipient.Character?.ViewTarget != null)
|
||||
{
|
||||
distance = Math.Min(distance, Vector2.Distance(recipient.Character.ViewTarget.WorldPosition, WorldPosition));
|
||||
}
|
||||
|
||||
float priority = 1.0f - MathUtils.InverseLerp(
|
||||
NetConfig.HighPrioCharacterPositionUpdateDistance,
|
||||
NetConfig.LowPrioCharacterPositionUpdateDistance,
|
||||
@@ -273,21 +278,21 @@ namespace Barotrauma
|
||||
switch ((NetEntityEvent.Type)extraData[0])
|
||||
{
|
||||
case NetEntityEvent.Type.InventoryState:
|
||||
msg.WriteRangedInteger(0, 0, 5);
|
||||
msg.WriteRangedInteger(0, 0, 6);
|
||||
msg.Write(GameMain.Server.EntityEventManager.Events.Last()?.ID ?? (ushort)0);
|
||||
Inventory.ServerWrite(msg, c);
|
||||
break;
|
||||
case NetEntityEvent.Type.Control:
|
||||
msg.WriteRangedInteger(1, 0, 5);
|
||||
msg.WriteRangedInteger(1, 0, 6);
|
||||
Client owner = (Client)extraData[1];
|
||||
msg.Write(owner != null && owner.Character == this && GameMain.Server.ConnectedClients.Contains(owner) ? owner.ID : (byte)0);
|
||||
break;
|
||||
case NetEntityEvent.Type.Status:
|
||||
msg.WriteRangedInteger(2, 0, 5);
|
||||
msg.WriteRangedInteger(2, 0, 6);
|
||||
WriteStatus(msg);
|
||||
break;
|
||||
case NetEntityEvent.Type.UpdateSkills:
|
||||
msg.WriteRangedInteger(3, 0, 5);
|
||||
msg.WriteRangedInteger(3, 0, 6);
|
||||
if (Info?.Job == null)
|
||||
{
|
||||
msg.Write((byte)0);
|
||||
@@ -306,15 +311,36 @@ namespace Barotrauma
|
||||
Limb attackLimb = extraData[1] as Limb;
|
||||
UInt16 targetEntityID = (UInt16)extraData[2];
|
||||
int targetLimbIndex = extraData.Length > 3 ? (int)extraData[3] : 0;
|
||||
msg.WriteRangedInteger(4, 0, 5);
|
||||
msg.WriteRangedInteger(4, 0, 6);
|
||||
msg.Write((byte)(Removed ? 255 : Array.IndexOf(AnimController.Limbs, attackLimb)));
|
||||
msg.Write(targetEntityID);
|
||||
msg.Write((byte)targetLimbIndex);
|
||||
break;
|
||||
case NetEntityEvent.Type.AssignCampaignInteraction:
|
||||
msg.WriteRangedInteger(5, 0, 5);
|
||||
msg.WriteRangedInteger(5, 0, 6);
|
||||
msg.Write((byte)CampaignInteractionType);
|
||||
break;
|
||||
case NetEntityEvent.Type.ObjectiveManagerOrderState:
|
||||
msg.WriteRangedInteger(6, 0, 6);
|
||||
if (!(AIController is HumanAIController controller))
|
||||
{
|
||||
msg.Write(false);
|
||||
break;
|
||||
}
|
||||
var currentOrderInfo = controller.ObjectiveManager.GetCurrentOrderInfo();
|
||||
if (!currentOrderInfo.HasValue)
|
||||
{
|
||||
msg.Write(false);
|
||||
break;
|
||||
}
|
||||
msg.Write(true);
|
||||
var orderPrefab = currentOrderInfo.Value.Order.Prefab;
|
||||
int orderIndex = Order.PrefabList.IndexOf(orderPrefab);
|
||||
msg.WriteRangedInteger(orderIndex, 0, Order.PrefabList.Count);
|
||||
if (!orderPrefab.HasOptions) { break; }
|
||||
int optionIndex = orderPrefab.Options.IndexOf(currentOrderInfo.Value.OrderOption);
|
||||
msg.WriteRangedInteger(optionIndex, 0, orderPrefab.Options.Length);
|
||||
break;
|
||||
default:
|
||||
DebugConsole.ThrowError("Invalid NetworkEvent type for entity " + ToString() + " (" + (NetEntityEvent.Type)extraData[0] + ")");
|
||||
break;
|
||||
@@ -524,29 +550,28 @@ namespace Barotrauma
|
||||
|
||||
msg.Write((byte)CampaignInteractionType);
|
||||
|
||||
// Current order
|
||||
if (info.CurrentOrder != null)
|
||||
|
||||
// Current orders
|
||||
msg.Write((byte)info.CurrentOrders.Count(o => o.Order != null));
|
||||
foreach (var orderInfo in info.CurrentOrders)
|
||||
{
|
||||
msg.Write(true);
|
||||
msg.Write((byte)Order.PrefabList.IndexOf(info.CurrentOrder.Prefab));
|
||||
msg.Write(info.CurrentOrder.TargetEntity == null ? (UInt16)0 : info.CurrentOrder.TargetEntity.ID);
|
||||
var hasOrderGiver = info.CurrentOrder.OrderGiver != null;
|
||||
if (orderInfo.Order == null) { continue; }
|
||||
msg.Write((byte)Order.PrefabList.IndexOf(orderInfo.Order.Prefab));
|
||||
msg.Write(orderInfo.Order.TargetEntity == null ? (UInt16)0 : orderInfo.Order.TargetEntity.ID);
|
||||
var hasOrderGiver = orderInfo.Order.OrderGiver != null;
|
||||
msg.Write(hasOrderGiver);
|
||||
if (hasOrderGiver) { msg.Write(info.CurrentOrder.OrderGiver.ID); }
|
||||
msg.Write((byte)(string.IsNullOrWhiteSpace(info.CurrentOrderOption) ? 0 : Array.IndexOf(info.CurrentOrder.Prefab.Options, info.CurrentOrderOption)));
|
||||
var hasTargetPosition = info.CurrentOrder.TargetPosition != null;
|
||||
if (hasOrderGiver) { msg.Write(orderInfo.Order.OrderGiver.ID); }
|
||||
msg.Write((byte)(string.IsNullOrWhiteSpace(orderInfo.OrderOption) ? 0 : Array.IndexOf(orderInfo.Order.Prefab.Options, orderInfo.OrderOption)));
|
||||
msg.Write((byte)orderInfo.ManualPriority);
|
||||
var hasTargetPosition = orderInfo.Order.TargetPosition != null;
|
||||
msg.Write(hasTargetPosition);
|
||||
if (hasTargetPosition)
|
||||
{
|
||||
msg.Write(info.CurrentOrder.TargetPosition.Position.X);
|
||||
msg.Write(info.CurrentOrder.TargetPosition.Position.Y);
|
||||
msg.Write(info.CurrentOrder.TargetPosition.Hull == null ? (UInt16)0 : info.CurrentOrder.TargetPosition.Hull.ID);
|
||||
msg.Write(orderInfo.Order.TargetPosition.Position.X);
|
||||
msg.Write(orderInfo.Order.TargetPosition.Position.Y);
|
||||
msg.Write(orderInfo.Order.TargetPosition.Hull == null ? (UInt16)0 : orderInfo.Order.TargetPosition.Hull.ID);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
msg.Write(false);
|
||||
}
|
||||
|
||||
TryWriteStatus(msg);
|
||||
|
||||
|
||||
@@ -73,17 +73,27 @@ namespace Barotrauma
|
||||
Stopwatch sw = new Stopwatch();
|
||||
sw.Start();
|
||||
|
||||
int consoleWidth = Console.WindowWidth;
|
||||
if (consoleWidth < 5) consoleWidth = 5;
|
||||
int consoleHeight = Console.WindowHeight;
|
||||
if (consoleHeight < 5) consoleHeight = 5;
|
||||
int consoleWidth = 0;
|
||||
int consoleHeight = 0;
|
||||
|
||||
if(!Console.IsOutputRedirected)
|
||||
{
|
||||
consoleWidth = Console.WindowWidth;
|
||||
if (consoleWidth < 5) consoleWidth = 5;
|
||||
consoleHeight = Console.WindowHeight;
|
||||
if (consoleHeight < 5) consoleHeight = 5;
|
||||
}
|
||||
|
||||
//dequeue messages
|
||||
lock (queuedMessages)
|
||||
{
|
||||
if (queuedMessages.Count > 0)
|
||||
{
|
||||
Console.CursorLeft = 0;
|
||||
|
||||
if (!Console.IsOutputRedirected)
|
||||
{
|
||||
Console.CursorLeft = 0;
|
||||
}
|
||||
while (queuedMessages.Count > 0)
|
||||
{
|
||||
ColoredText msg = queuedMessages.Dequeue();
|
||||
@@ -102,15 +112,21 @@ namespace Barotrauma
|
||||
|
||||
if (msg.IsCommand) commandMemory.Add(msgTxt);
|
||||
|
||||
int paddingLen = consoleWidth - (msg.Text.Length % consoleWidth)-1;
|
||||
msgTxt += new string(' ', paddingLen>0 ? paddingLen : 0);
|
||||
if(!Console.IsOutputRedirected)
|
||||
{
|
||||
int paddingLen = consoleWidth - (msg.Text.Length % consoleWidth) - 1;
|
||||
msgTxt += new string(' ', paddingLen > 0 ? paddingLen : 0);
|
||||
|
||||
Console.ForegroundColor = XnaToConsoleColor.Convert(msg.Color);
|
||||
Console.ForegroundColor = XnaToConsoleColor.Convert(msg.Color);
|
||||
}
|
||||
Console.WriteLine(msgTxt);
|
||||
|
||||
if (sw.ElapsedMilliseconds >= maxTime) { break; }
|
||||
}
|
||||
RewriteInputToCommandLine(input);
|
||||
if(!Console.IsOutputRedirected)
|
||||
{
|
||||
RewriteInputToCommandLine(input);
|
||||
}
|
||||
}
|
||||
if (Messages.Count > MaxMessages)
|
||||
{
|
||||
@@ -118,73 +134,78 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
//read player input
|
||||
bool rewriteInput = false;
|
||||
while (Console.KeyAvailable)
|
||||
// No good way to display input when console output is redirected, and can't read from redirected input using KeyAvailable.
|
||||
if(!Console.IsOutputRedirected && !Console.IsInputRedirected)
|
||||
{
|
||||
if (sw.ElapsedMilliseconds >= maxTime)
|
||||
//read player input
|
||||
bool rewriteInput = false;
|
||||
while (Console.KeyAvailable)
|
||||
{
|
||||
rewriteInput = false;
|
||||
break;
|
||||
}
|
||||
rewriteInput = true;
|
||||
ConsoleKeyInfo key = Console.ReadKey(true);
|
||||
switch (key.Key)
|
||||
{
|
||||
case ConsoleKey.Enter:
|
||||
lock (QueuedCommands)
|
||||
{
|
||||
QueuedCommands.Add(input);
|
||||
}
|
||||
input = "";
|
||||
memoryIndex = -1;
|
||||
if (sw.ElapsedMilliseconds >= maxTime)
|
||||
{
|
||||
rewriteInput = false;
|
||||
break;
|
||||
case ConsoleKey.Backspace:
|
||||
if (input.Length > 0) input = input.Substring(0, input.Length - 1);
|
||||
memoryIndex = -1;
|
||||
break;
|
||||
case ConsoleKey.LeftArrow:
|
||||
input = AutoComplete(input, -1);
|
||||
break;
|
||||
case ConsoleKey.RightArrow:
|
||||
input = AutoComplete(input, 1);
|
||||
break;
|
||||
case ConsoleKey.UpArrow:
|
||||
memoryIndex--;
|
||||
if (memoryIndex < 0) memoryIndex = commandMemory.Count - 1;
|
||||
if (memoryIndex >= commandMemory.Count) memoryIndex = commandMemory.Count - 1;
|
||||
if (memoryIndex >= 0)
|
||||
{
|
||||
input = commandMemory[memoryIndex];
|
||||
}
|
||||
break;
|
||||
case ConsoleKey.DownArrow:
|
||||
memoryIndex++;
|
||||
if (memoryIndex < 0) memoryIndex = 0;
|
||||
if (memoryIndex >= commandMemory.Count) memoryIndex = 0;
|
||||
if (commandMemory.Count>0)
|
||||
{
|
||||
input = commandMemory[memoryIndex];
|
||||
}
|
||||
break;
|
||||
case ConsoleKey.Tab:
|
||||
if (input.Length > 0)
|
||||
{
|
||||
input = AutoComplete(input, 0);
|
||||
}
|
||||
rewriteInput = true;
|
||||
ConsoleKeyInfo key = Console.ReadKey(true);
|
||||
switch (key.Key)
|
||||
{
|
||||
case ConsoleKey.Enter:
|
||||
lock (QueuedCommands)
|
||||
{
|
||||
QueuedCommands.Add(input);
|
||||
}
|
||||
input = "";
|
||||
memoryIndex = -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (key.KeyChar != 0)
|
||||
{
|
||||
input += key.KeyChar;
|
||||
break;
|
||||
case ConsoleKey.Backspace:
|
||||
if (input.Length > 0) input = input.Substring(0, input.Length - 1);
|
||||
ResetAutoComplete();
|
||||
memoryIndex = -1;
|
||||
}
|
||||
ResetAutoComplete();
|
||||
break;
|
||||
break;
|
||||
case ConsoleKey.LeftArrow:
|
||||
input = AutoComplete(input, -1);
|
||||
break;
|
||||
case ConsoleKey.RightArrow:
|
||||
input = AutoComplete(input, 1);
|
||||
break;
|
||||
case ConsoleKey.UpArrow:
|
||||
memoryIndex--;
|
||||
if (memoryIndex < 0) memoryIndex = commandMemory.Count - 1;
|
||||
if (memoryIndex >= commandMemory.Count) memoryIndex = commandMemory.Count - 1;
|
||||
if (memoryIndex >= 0)
|
||||
{
|
||||
input = commandMemory[memoryIndex];
|
||||
}
|
||||
break;
|
||||
case ConsoleKey.DownArrow:
|
||||
memoryIndex++;
|
||||
if (memoryIndex < 0) memoryIndex = 0;
|
||||
if (memoryIndex >= commandMemory.Count) memoryIndex = 0;
|
||||
if (commandMemory.Count>0)
|
||||
{
|
||||
input = commandMemory[memoryIndex];
|
||||
}
|
||||
break;
|
||||
case ConsoleKey.Tab:
|
||||
if (input.Length > 0)
|
||||
{
|
||||
input = AutoComplete(input, 0);
|
||||
memoryIndex = -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (key.KeyChar != 0)
|
||||
{
|
||||
input += key.KeyChar;
|
||||
memoryIndex = -1;
|
||||
}
|
||||
ResetAutoComplete();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rewriteInput) { RewriteInputToCommandLine(input); }
|
||||
}
|
||||
if (rewriteInput) { RewriteInputToCommandLine(input); }
|
||||
|
||||
sw.Stop();
|
||||
}
|
||||
@@ -1333,7 +1354,15 @@ namespace Barotrauma
|
||||
commands.Add(new Command("startgame|startround|start", "start/startgame/startround: Start a new round.", (string[] args) =>
|
||||
{
|
||||
if (Screen.Selected == GameMain.GameScreen) { return; }
|
||||
if (!GameMain.Server.StartGame()) NewMessage("Failed to start a new round", Color.Yellow);
|
||||
if (GameMain.GameSession?.GameMode is MultiPlayerCampaign mpCampaign &&
|
||||
GameMain.NetLobbyScreen.SelectedMode == GameModePreset.MultiPlayerCampaign)
|
||||
{
|
||||
MultiPlayerCampaign.LoadCampaign(GameMain.GameSession.SavePath);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!GameMain.Server.StartGame()) { NewMessage("Failed to start a new round", Color.Yellow); }
|
||||
}
|
||||
}));
|
||||
|
||||
commands.Add(new Command("endgame|endround|end", "end/endgame/endround: End the current round.", (string[] args) =>
|
||||
@@ -1708,14 +1737,15 @@ namespace Barotrauma
|
||||
(Client client, Vector2 cursorWorldPos, string[] args) =>
|
||||
{
|
||||
Vector2 explosionPos = cursorWorldPos;
|
||||
float range = 500, force = 10, damage = 50, structureDamage = 10, itemDamage = 100, empStrength = 0.0f; ;
|
||||
float range = 500, force = 10, damage = 50, structureDamage = 10, itemDamage = 100, empStrength = 0.0f, ballastFloraStrength = 50f;
|
||||
if (args.Length > 0) float.TryParse(args[0], out range);
|
||||
if (args.Length > 1) float.TryParse(args[1], out force);
|
||||
if (args.Length > 2) float.TryParse(args[2], out damage);
|
||||
if (args.Length > 3) float.TryParse(args[3], out structureDamage);
|
||||
if (args.Length > 4) float.TryParse(args[4], out itemDamage);
|
||||
if (args.Length > 5) float.TryParse(args[5], out empStrength);
|
||||
new Explosion(range, force, damage, structureDamage, itemDamage, empStrength).Explode(explosionPos, null);
|
||||
if (args.Length > 6) float.TryParse(args[6], out ballastFloraStrength);
|
||||
new Explosion(range, force, damage, structureDamage, itemDamage, empStrength, ballastFloraStrength).Explode(explosionPos, null);
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
using Barotrauma.Networking;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class AbandonedOutpostMission : Mission
|
||||
{
|
||||
public override void ServerWriteInitial(IWriteMessage msg, Client c)
|
||||
{
|
||||
if (characters.Count == 0)
|
||||
{
|
||||
throw new InvalidOperationException("Server attempted to write AbandonedOutpostMission data when no characters had been spawned.");
|
||||
}
|
||||
|
||||
msg.Write((byte)characters.Count);
|
||||
foreach (Character character in characters)
|
||||
{
|
||||
character.WriteSpawnData(msg, character.ID, restrictMessageSize: false);
|
||||
msg.Write((ushort)characterItems[character].Count());
|
||||
foreach (Item item in characterItems[character])
|
||||
{
|
||||
item.WriteSpawnData(msg, item.ID, item.ParentInventory.Owner?.ID ?? Entity.NullEntityID, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,4 @@
|
||||
using Barotrauma.Networking;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
|
||||
@@ -21,31 +21,6 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public override void AssignTeamIDs(List<Client> clients)
|
||||
{
|
||||
List<Client> randList = new List<Client>(clients);
|
||||
for (int i = 0; i < randList.Count; i++)
|
||||
{
|
||||
Client a = randList[i];
|
||||
int oi = Rand.Range(0, randList.Count - 1);
|
||||
Client b = randList[oi];
|
||||
randList[i] = b;
|
||||
randList[oi] = a;
|
||||
}
|
||||
int halfPlayers = randList.Count / 2;
|
||||
for (int i = 0; i < randList.Count; i++)
|
||||
{
|
||||
if (i < halfPlayers)
|
||||
{
|
||||
randList[i].TeamID = Character.TeamType.Team1;
|
||||
}
|
||||
else
|
||||
{
|
||||
randList[i].TeamID = Character.TeamType.Team2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime)
|
||||
{
|
||||
if (!initialized)
|
||||
@@ -54,11 +29,11 @@ namespace Barotrauma
|
||||
crews[1].Clear();
|
||||
foreach (Character character in Character.CharacterList)
|
||||
{
|
||||
if (character.TeamID == Character.TeamType.Team1)
|
||||
if (character.TeamID == CharacterTeamType.Team1)
|
||||
{
|
||||
crews[0].Add(character);
|
||||
}
|
||||
else if (character.TeamID == Character.TeamType.Team2)
|
||||
else if (character.TeamID == CharacterTeamType.Team2)
|
||||
{
|
||||
crews[1].Add(character);
|
||||
}
|
||||
@@ -88,7 +63,7 @@ namespace Barotrauma
|
||||
//make sure nobody in the other team can be revived because that would be pretty weird
|
||||
crews[1 - i].ForEach(c => { if (!c.IsDead) c.Kill(CauseOfDeathType.Unknown, null); });
|
||||
|
||||
GameMain.GameSession.WinningTeam = i == 0 ? Character.TeamType.Team1 : Character.TeamType.Team2;
|
||||
GameMain.GameSession.WinningTeam = i == 0 ? CharacterTeamType.Team1 : CharacterTeamType.Team2;
|
||||
|
||||
state = 1;
|
||||
break;
|
||||
@@ -99,10 +74,10 @@ namespace Barotrauma
|
||||
{
|
||||
if (teamDead[0] && teamDead[1])
|
||||
{
|
||||
GameMain.GameSession.WinningTeam = Character.TeamType.None;
|
||||
GameMain.GameSession.WinningTeam = CharacterTeamType.None;
|
||||
if (GameMain.Server != null) { GameMain.Server.EndGame(); }
|
||||
}
|
||||
else if (GameMain.GameSession.WinningTeam != Character.TeamType.None)
|
||||
else if (GameMain.GameSession.WinningTeam != CharacterTeamType.None)
|
||||
{
|
||||
GameMain.Server.EndGame();
|
||||
}
|
||||
|
||||
@@ -6,6 +6,12 @@ namespace Barotrauma
|
||||
{
|
||||
public override void ServerWriteInitial(IWriteMessage msg, Client c)
|
||||
{
|
||||
msg.Write((byte)caves.Count);
|
||||
foreach (var cave in caves)
|
||||
{
|
||||
msg.Write((byte)(Level.Loaded == null || !Level.Loaded.Caves.Contains(cave) ? 255 : Level.Loaded.Caves.IndexOf(cave)));
|
||||
}
|
||||
|
||||
foreach (var kvp in SpawnedResources)
|
||||
{
|
||||
msg.Write((byte)kvp.Value.Count);
|
||||
|
||||
@@ -4,8 +4,11 @@ namespace Barotrauma
|
||||
{
|
||||
partial class NestMission : Mission
|
||||
{
|
||||
private Level.Cave selectedCave;
|
||||
|
||||
public override void ServerWriteInitial(IWriteMessage msg, Client c)
|
||||
{
|
||||
msg.Write((byte)(selectedCave == null || Level.Loaded == null || !Level.Loaded.Caves.Contains(selectedCave) ? 255 : Level.Loaded.Caves.IndexOf(selectedCave)));
|
||||
msg.Write(nestPosition.X);
|
||||
msg.Write(nestPosition.Y);
|
||||
msg.Write((ushort)items.Count);
|
||||
|
||||
@@ -361,7 +361,7 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
#if !DEBUG
|
||||
if (Server?.OwnerConnection == null && !Console.IsOutputRedirected)
|
||||
if (Server?.OwnerConnection == null)
|
||||
{
|
||||
DebugConsole.UpdateCommandLine((int)(Timing.Accumulator * 800));
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -6,9 +7,12 @@ namespace Barotrauma
|
||||
{
|
||||
public void SellBackPurchasedItems(List<PurchasedItem> itemsToSell)
|
||||
{
|
||||
// Check all the prices before starting the transaction
|
||||
// to make sure the modifiers stay the same for the whole transaction
|
||||
Dictionary<ItemPrefab, int> buyValues = GetBuyValuesAtCurrentLocation(itemsToSell.Select(i => i.ItemPrefab));
|
||||
foreach (PurchasedItem item in itemsToSell)
|
||||
{
|
||||
var itemValue = GetBuyValueAtCurrentLocation(item);
|
||||
var itemValue = item.Quantity * buyValues[item.ItemPrefab];
|
||||
Location.StoreCurrentBalance -= itemValue;
|
||||
campaign.Money += itemValue;
|
||||
PurchasedItems.Remove(item);
|
||||
@@ -17,9 +21,12 @@ namespace Barotrauma
|
||||
|
||||
public void BuyBackSoldItems(List<SoldItem> itemsToBuy)
|
||||
{
|
||||
// Check all the prices before starting the transaction
|
||||
// to make sure the modifiers stay the same for the whole transaction
|
||||
Dictionary<ItemPrefab, int> sellValues = GetSellValuesAtCurrentLocation(itemsToBuy.Select(i => i.ItemPrefab));
|
||||
foreach (SoldItem item in itemsToBuy)
|
||||
{
|
||||
var itemValue = GetSellValueAtCurrentLocation(item.ItemPrefab);
|
||||
var itemValue = sellValues[item.ItemPrefab];
|
||||
if (Location.StoreCurrentBalance < itemValue || item.Removed) { continue; }
|
||||
Location.StoreCurrentBalance += itemValue;
|
||||
campaign.Money -= itemValue;
|
||||
@@ -29,10 +36,13 @@ namespace Barotrauma
|
||||
|
||||
public void SellItems(List<SoldItem> itemsToSell)
|
||||
{
|
||||
// Check all the prices before starting the transaction
|
||||
// to make sure the modifiers stay the same for the whole transaction
|
||||
Dictionary<ItemPrefab, int> sellValues = GetSellValuesAtCurrentLocation(itemsToSell.Select(i => i.ItemPrefab));
|
||||
var canAddToRemoveQueue = (GameMain.NetworkMember == null || GameMain.NetworkMember.IsServer) && Entity.Spawner != null;
|
||||
foreach (SoldItem item in itemsToSell)
|
||||
{
|
||||
var itemValue = GetSellValueAtCurrentLocation(item.ItemPrefab);
|
||||
var itemValue = sellValues[item.ItemPrefab];
|
||||
|
||||
// check if the store can afford the item and if the item hasn't been removed already
|
||||
if (Location.StoreCurrentBalance < itemValue || item.Removed) { continue; }
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Barotrauma.Networking;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -13,10 +12,11 @@ namespace Barotrauma
|
||||
|
||||
public override void ShowStartMessage()
|
||||
{
|
||||
if (Mission == null) return;
|
||||
|
||||
GameServer.Log(TextManager.Get("Mission") + ": " + Mission.Name, Networking.ServerLog.MessageType.ServerMessage);
|
||||
GameServer.Log(Mission.Description, Networking.ServerLog.MessageType.ServerMessage);
|
||||
foreach (Mission mission in Missions)
|
||||
{
|
||||
GameServer.Log(TextManager.Get("Mission") + ": " + mission.Name, ServerLog.MessageType.ServerMessage);
|
||||
GameServer.Log(mission.Description, ServerLog.MessageType.ServerMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,11 @@
|
||||
{
|
||||
public override void ShowStartMessage()
|
||||
{
|
||||
if (mission == null) return;
|
||||
|
||||
Networking.GameServer.Log(TextManager.Get("Mission") + ": " + mission.Name, Networking.ServerLog.MessageType.ServerMessage);
|
||||
Networking.GameServer.Log(mission.Description, Networking.ServerLog.MessageType.ServerMessage);
|
||||
foreach (Mission mission in missions)
|
||||
{
|
||||
Networking.GameServer.Log(TextManager.Get("Mission") + ": " + mission.Name, Networking.ServerLog.MessageType.ServerMessage);
|
||||
Networking.GameServer.Log(mission.Description, Networking.ServerLog.MessageType.ServerMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+16
-4
@@ -225,7 +225,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.Items.Where(it => it != null && it.SpawnedInOutpost && it.OriginalModuleIndex > 0).Distinct());
|
||||
Map.CurrentLocation.RegisterTakenItems(c.Inventory.AllItems.Where(it => it.SpawnedInOutpost && it.OriginalModuleIndex > 0));
|
||||
}
|
||||
|
||||
if (c.Info != null && c.IsBot)
|
||||
@@ -367,6 +367,8 @@ namespace Barotrauma
|
||||
{
|
||||
if (CoroutineManager.IsCoroutineRunning("LevelTransition")) { return; }
|
||||
|
||||
Map?.Radiation.UpdateRadiation(deltaTime);
|
||||
|
||||
base.Update(deltaTime);
|
||||
if (Level.Loaded != null)
|
||||
{
|
||||
@@ -441,9 +443,16 @@ namespace Barotrauma
|
||||
foreach (Mission mission in map.CurrentLocation.AvailableMissions)
|
||||
{
|
||||
msg.Write(mission.Prefab.Identifier);
|
||||
Location missionDestination = mission.Locations[0] == map.CurrentLocation ? mission.Locations[1] : mission.Locations[0];
|
||||
LocationConnection connection = map.CurrentLocation.Connections.Find(c => c.OtherLocation(map.CurrentLocation) == missionDestination);
|
||||
msg.Write((byte)map.CurrentLocation.Connections.IndexOf(connection));
|
||||
if (mission.Locations[0] == mission.Locations[1])
|
||||
{
|
||||
msg.Write((byte)255);
|
||||
}
|
||||
else
|
||||
{
|
||||
Location missionDestination = mission.Locations[0] == map.CurrentLocation ? mission.Locations[1] : mission.Locations[0];
|
||||
LocationConnection connection = map.CurrentLocation.Connections.Find(c => c.OtherLocation(map.CurrentLocation) == missionDestination);
|
||||
msg.Write((byte)map.CurrentLocation.Connections.IndexOf(connection));
|
||||
}
|
||||
}
|
||||
|
||||
// Store balance
|
||||
@@ -773,6 +782,9 @@ namespace Barotrauma
|
||||
element.Add(new XAttribute("campaignid", CampaignID));
|
||||
XElement modeElement = new XElement("MultiPlayerCampaign",
|
||||
new XAttribute("money", Money),
|
||||
new XAttribute("purchasedlostshuttles", PurchasedLostShuttles),
|
||||
new XAttribute("purchasedhullrepairs", PurchasedHullRepairs),
|
||||
new XAttribute("purchaseditemrepairs", PurchasedItemRepairs),
|
||||
new XAttribute("cheatsenabled", CheatsEnabled));
|
||||
CampaignMetadata?.Save(modeElement);
|
||||
Map.Save(modeElement);
|
||||
|
||||
@@ -64,6 +64,7 @@ namespace Barotrauma
|
||||
|
||||
partial void EndReadyCheck()
|
||||
{
|
||||
if (IsFinished) { return; }
|
||||
IsFinished = true;
|
||||
foreach (Client client in ActivePlayers)
|
||||
{
|
||||
|
||||
@@ -5,17 +5,14 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
partial class DockingPort : ItemComponent, IDrawableComponent, IServerSerializable
|
||||
{
|
||||
|
||||
private UInt16 originalDockingTargetID;
|
||||
|
||||
public void ServerWrite(IWriteMessage msg, Client c, object[] extraData = null)
|
||||
{
|
||||
msg.Write(docked);
|
||||
|
||||
if (docked)
|
||||
{
|
||||
msg.Write(originalDockingTargetID);
|
||||
msg.Write(hulls != null && hulls[0] != null && hulls[1] != null && gap != null);
|
||||
msg.Write(DockingTarget.item.ID);
|
||||
msg.Write(IsLocked);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,13 @@ namespace Barotrauma.Items.Components
|
||||
set;
|
||||
}
|
||||
|
||||
[Serialize("0,0,0,0", true, description: "The amount of padding around the text in pixels (left,top,right,bottom).")]
|
||||
public Vector4 Padding
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public override void Move(Vector2 amount)
|
||||
{
|
||||
//do nothing
|
||||
|
||||
@@ -42,6 +42,15 @@ namespace Barotrauma.Items.Components
|
||||
msg.WriteRangedInteger((int)(flowPercentage / 10.0f), -10, 10);
|
||||
msg.Write(IsActive);
|
||||
msg.Write(Hijacked);
|
||||
if (TargetLevel != null)
|
||||
{
|
||||
msg.Write(true);
|
||||
msg.Write(TargetLevel.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg.Write(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
using Barotrauma.Networking;
|
||||
using FarseerPhysics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
@@ -18,7 +15,7 @@ namespace Barotrauma.Items.Components
|
||||
for (int i = 0; i < Connections.Count; i++)
|
||||
{
|
||||
wires[i] = new List<Wire>();
|
||||
for (int j = 0; j < Connection.MaxLinked; j++)
|
||||
for (int j = 0; j < Connections[i].MaxWires; j++)
|
||||
{
|
||||
ushort wireId = msg.ReadUInt16();
|
||||
|
||||
@@ -68,9 +65,9 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
item.CreateServerEvent(this);
|
||||
c.Character.Inventory?.CreateNetworkEvent();
|
||||
for (int i = 0; i < 2; i++)
|
||||
foreach (Item heldItem in c.Character.HeldItems)
|
||||
{
|
||||
var selectedWire = c.Character.SelectedItems[i]?.GetComponent<Wire>();
|
||||
var selectedWire = heldItem?.GetComponent<Wire>();
|
||||
if (selectedWire == null) { continue; }
|
||||
|
||||
selectedWire.CreateNetworkEvent();
|
||||
|
||||
+12
-6
@@ -1,7 +1,5 @@
|
||||
using Barotrauma.Networking;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma.Items.Components
|
||||
{
|
||||
@@ -13,7 +11,7 @@ namespace Barotrauma.Items.Components
|
||||
string[] elementValues = new string[customInterfaceElementList.Count];
|
||||
for (int i = 0; i < customInterfaceElementList.Count; i++)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(customInterfaceElementList[i].PropertyName))
|
||||
if (customInterfaceElementList[i].HasPropertyName)
|
||||
{
|
||||
elementValues[i] = msg.ReadString();
|
||||
}
|
||||
@@ -28,9 +26,17 @@ namespace Barotrauma.Items.Components
|
||||
{
|
||||
for (int i = 0; i < customInterfaceElementList.Count; i++)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(customInterfaceElementList[i].PropertyName))
|
||||
if (customInterfaceElementList[i].HasPropertyName)
|
||||
{
|
||||
TextChanged(customInterfaceElementList[i], elementValues[i]);
|
||||
if (!customInterfaceElementList[i].IsIntegerInput)
|
||||
{
|
||||
TextChanged(customInterfaceElementList[i], elementValues[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
int.TryParse(elementValues[i], out int value);
|
||||
ValueChanged(customInterfaceElementList[i], value);
|
||||
}
|
||||
}
|
||||
else if (customInterfaceElementList[i].ContinuousSignal)
|
||||
{
|
||||
@@ -60,7 +66,7 @@ namespace Barotrauma.Items.Components
|
||||
//extradata contains an array of buttons clicked by a client (or nothing if nothing was clicked)
|
||||
for (int i = 0; i < customInterfaceElementList.Count; i++)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(customInterfaceElementList[i].PropertyName))
|
||||
if (customInterfaceElementList[i].HasPropertyName)
|
||||
{
|
||||
msg.Write(customInterfaceElementList[i].Signal);
|
||||
}
|
||||
|
||||
@@ -37,9 +37,16 @@ namespace Barotrauma.Items.Components
|
||||
public void SyncHistory()
|
||||
{
|
||||
//split too long messages to multiple parts
|
||||
int msgIndex = 0;
|
||||
foreach (string str in messageHistory)
|
||||
{
|
||||
string msgToSend = str;
|
||||
if (string.IsNullOrEmpty(msgToSend))
|
||||
{
|
||||
item.CreateServerEvent(this, new object[] { msgIndex, msgToSend });
|
||||
msgIndex++;
|
||||
continue;
|
||||
}
|
||||
if (msgToSend.Length > MaxMessageLength)
|
||||
{
|
||||
List<string> splitMessage = msgToSend.Split(' ').ToList();
|
||||
@@ -62,20 +69,21 @@ namespace Barotrauma.Items.Components
|
||||
if (!splitMessage.Any()) { break; }
|
||||
tempMsg += " ";
|
||||
} while (tempMsg.Length + splitMessage[0].Length < MaxMessageLength);
|
||||
item.CreateServerEvent(this, new string[] { msgToSend });
|
||||
item.CreateServerEvent(this, new object[] { msgIndex, tempMsg });
|
||||
msgToSend = msgToSend.Remove(0, tempMsg.Length);
|
||||
}
|
||||
}
|
||||
if (!string.IsNullOrEmpty(msgToSend))
|
||||
{
|
||||
item.CreateServerEvent(this, new string[] { msgToSend });
|
||||
}
|
||||
}
|
||||
item.CreateServerEvent(this, new object[] { msgIndex, msgToSend });
|
||||
}
|
||||
msgIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
public void ServerWrite(IWriteMessage msg, Client c, object[] extraData = null)
|
||||
{
|
||||
if (extraData.Length > 2 && extraData[2] is string str)
|
||||
if (extraData.Length > 3 && extraData[3] is string str)
|
||||
{
|
||||
msg.Write(str);
|
||||
}
|
||||
|
||||
@@ -10,25 +10,30 @@ namespace Barotrauma
|
||||
{
|
||||
public void ServerRead(ClientNetObject type, IReadMessage msg, Client c)
|
||||
{
|
||||
List<Item> prevItems = new List<Item>(Items);
|
||||
List<Item> prevItems = new List<Item>(AllItems.Distinct());
|
||||
|
||||
byte itemCount = msg.ReadByte();
|
||||
ushort[] newItemIDs = new ushort[itemCount];
|
||||
for (int i = 0; i < itemCount; i++)
|
||||
byte slotCount = msg.ReadByte();
|
||||
List<ushort>[] newItemIDs = new List<ushort>[slotCount];
|
||||
for (int i = 0; i < slotCount; i++)
|
||||
{
|
||||
newItemIDs[i] = msg.ReadUInt16();
|
||||
newItemIDs[i] = new List<ushort>();
|
||||
int itemCount = msg.ReadRangedInteger(0, MaxStackSize);
|
||||
for (int j = 0; j < itemCount; j++)
|
||||
{
|
||||
newItemIDs[i].Add(msg.ReadUInt16());
|
||||
}
|
||||
}
|
||||
|
||||
if (c == null || c.Character == null) return;
|
||||
|
||||
if (c == null || c.Character == null) { return; }
|
||||
|
||||
bool accessible = c.Character.CanAccessInventory(this);
|
||||
if (this is CharacterInventory && accessible)
|
||||
if (this is CharacterInventory characterInventory && accessible)
|
||||
{
|
||||
if (Owner == null || !(Owner is Character))
|
||||
if (Owner == null || !(Owner is Character ownerCharacter))
|
||||
{
|
||||
accessible = false;
|
||||
}
|
||||
else if (!((CharacterInventory)this).AccessibleWhenAlive && !((Character)Owner).IsDead)
|
||||
else if (!characterInventory.AccessibleWhenAlive && !ownerCharacter.IsDead)
|
||||
{
|
||||
accessible = false;
|
||||
}
|
||||
@@ -42,28 +47,28 @@ namespace Barotrauma
|
||||
CreateNetworkEvent();
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
if (!(Entity.FindEntityByID(newItemIDs[i]) is Item item)) { continue; }
|
||||
item.PositionUpdateInterval = 0.0f;
|
||||
if (item.ParentInventory != null && item.ParentInventory != this)
|
||||
foreach (ushort id in newItemIDs[i])
|
||||
{
|
||||
item.ParentInventory.CreateNetworkEvent();
|
||||
if (!(Entity.FindEntityByID(id) is Item item)) { continue; }
|
||||
item.PositionUpdateInterval = 0.0f;
|
||||
if (item.ParentInventory != null && item.ParentInventory != this)
|
||||
{
|
||||
item.ParentInventory.CreateNetworkEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
List<Inventory> prevItemInventories = new List<Inventory>(Items.Select(i => i?.ParentInventory));
|
||||
|
||||
List<Inventory> prevItemInventories = new List<Inventory>() { this };
|
||||
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
Item newItem = newItemIDs[i] == 0 ? null : Entity.FindEntityByID(newItemIDs[i]) as Item;
|
||||
prevItemInventories.Add(newItem?.ParentInventory);
|
||||
|
||||
if (newItemIDs[i] == 0 || (newItem != Items[i]))
|
||||
foreach (Item item in slots[i].Items.ToList())
|
||||
{
|
||||
if (Items[i] != null)
|
||||
if (!newItemIDs[i].Contains(item.ID))
|
||||
{
|
||||
Item droppedItem = Items[i];
|
||||
Item droppedItem = item;
|
||||
Entity prevOwner = Owner;
|
||||
droppedItem.Drop(null);
|
||||
|
||||
@@ -84,15 +89,20 @@ namespace Barotrauma
|
||||
droppedItem.body.SetTransform(prevOwner.SimPosition, 0.0f);
|
||||
}
|
||||
}
|
||||
System.Diagnostics.Debug.Assert(Items[i] == null);
|
||||
}
|
||||
|
||||
foreach (ushort id in newItemIDs[i])
|
||||
{
|
||||
Item newItem = id == 0 ? null : Entity.FindEntityByID(id) as Item;
|
||||
prevItemInventories.Add(newItem?.ParentInventory);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < capacity; i++)
|
||||
{
|
||||
if (newItemIDs[i] > 0)
|
||||
foreach (ushort id in newItemIDs[i])
|
||||
{
|
||||
if (!(Entity.FindEntityByID(newItemIDs[i]) is Item item) || item == Items[i]) { continue; }
|
||||
if (!(Entity.FindEntityByID(id) is Item item) || slots[i].Contains(item)) { continue; }
|
||||
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
@@ -101,9 +111,9 @@ namespace Barotrauma
|
||||
|
||||
if (!prevItems.Contains(item) && !item.CanClientAccess(c))
|
||||
{
|
||||
#if DEBUG || UNSTABLE
|
||||
#if DEBUG || UNSTABLE
|
||||
DebugConsole.NewMessage($"Client {c.Name} failed to pick up item \"{item}\" (parent inventory: {(item.ParentInventory?.Owner.ToString() ?? "null")}). No access.", Color.Yellow);
|
||||
#endif
|
||||
#endif
|
||||
if (item.body != null && !c.PendingPositionUpdates.Contains(item))
|
||||
{
|
||||
c.PendingPositionUpdates.Enqueue(item);
|
||||
@@ -115,9 +125,9 @@ namespace Barotrauma
|
||||
TryPutItem(item, i, true, true, c.Character, false);
|
||||
for (int j = 0; j < capacity; j++)
|
||||
{
|
||||
if (Items[j] == item && newItemIDs[j] != item.ID)
|
||||
if (slots[j].Contains(item) && !newItemIDs[j].Contains(item.ID))
|
||||
{
|
||||
Items[j] = null;
|
||||
slots[j].RemoveItem(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -129,7 +139,7 @@ namespace Barotrauma
|
||||
if (prevInventory != this) { prevInventory?.CreateNetworkEvent(); }
|
||||
}
|
||||
|
||||
foreach (Item item in Items.Distinct())
|
||||
foreach (Item item in AllItems.Distinct())
|
||||
{
|
||||
if (item == null) { continue; }
|
||||
if (!prevItems.Contains(item))
|
||||
@@ -148,7 +158,7 @@ namespace Barotrauma
|
||||
foreach (Item item in prevItems.Distinct())
|
||||
{
|
||||
if (item == null) { continue; }
|
||||
if (!Items.Contains(item))
|
||||
if (!AllItems.Contains(item))
|
||||
{
|
||||
if (Owner == c.Character)
|
||||
{
|
||||
|
||||
@@ -240,8 +240,6 @@ namespace Barotrauma
|
||||
{
|
||||
if (GameMain.Server == null) { return; }
|
||||
|
||||
int initialLength = msg.LengthBytes;
|
||||
|
||||
msg.Write(Prefab.OriginalName);
|
||||
msg.Write(Prefab.Identifier);
|
||||
msg.Write(Description != prefab.Description);
|
||||
@@ -294,11 +292,6 @@ namespace Barotrauma
|
||||
{
|
||||
msg.Write(nameTag.WrittenName ?? "");
|
||||
}
|
||||
|
||||
if (msg.LengthBytes - initialLength >= 255)
|
||||
{
|
||||
DebugConsole.ThrowError($"Too much data in an item spawn message. Item: \"{Prefab.Identifier}\", msg bytes: {(msg.LengthBytes - initialLength)}, description changed: {(Description != prefab.Description)}, description: {Description}, tags changed: {tagsChanged}, tags: {Tags}");
|
||||
}
|
||||
}
|
||||
|
||||
partial void UpdateNetPosition(float deltaTime)
|
||||
|
||||
@@ -58,10 +58,14 @@ namespace Barotrauma.MapCreatures.Behavior
|
||||
msg.Write(branch.Health);
|
||||
}
|
||||
|
||||
public void ServerWriteInfect(IWriteMessage msg, UInt16 itemID, bool infect)
|
||||
public void ServerWriteInfect(IWriteMessage msg, UInt16 itemID, bool infect, BallastFloraBranch infector = null)
|
||||
{
|
||||
msg.Write(itemID);
|
||||
msg.Write(infect);
|
||||
if (infect)
|
||||
{
|
||||
msg.Write(infector?.ID ?? -1);
|
||||
}
|
||||
}
|
||||
|
||||
public void ServerWriteBranchRemove(IWriteMessage msg, BallastFloraBranch branch)
|
||||
|
||||
@@ -93,7 +93,9 @@ namespace Barotrauma
|
||||
behavior.ServerWriteBranchRemove(message, branch);
|
||||
break;
|
||||
case BallastFloraBehavior.NetworkHeader.Infect when extraData.Length >= 4 && extraData[2] is UInt16 itemID && extraData[3] is bool infect:
|
||||
behavior.ServerWriteInfect(message, itemID, infect);
|
||||
BallastFloraBranch infector = null;
|
||||
if (extraData.Length >= 5 && extraData[4] is BallastFloraBranch b) { infector = b; }
|
||||
behavior.ServerWriteInfect(message, itemID, infect, infector);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -223,7 +225,7 @@ namespace Barotrauma
|
||||
byte decalIndex = msg.ReadByte();
|
||||
float decalAlpha = msg.ReadRangedSingle(0.0f, 1.0f, 255);
|
||||
if (decalIndex < 0 || decalIndex >= decals.Count) { return; }
|
||||
if (c.Character != null && c.Character.AllowInput && c.Character.SelectedItems.Any(it => it?.GetComponent<Sprayer>() != null))
|
||||
if (c.Character != null && c.Character.AllowInput && c.Character.HeldItems.Any(it => it.GetComponent<Sprayer>() != null))
|
||||
{
|
||||
decals[decalIndex].BaseAlpha = decalAlpha;
|
||||
}
|
||||
@@ -240,7 +242,7 @@ namespace Barotrauma
|
||||
Color color = new Color(msg.ReadUInt32());
|
||||
|
||||
//TODO: verify the client is close enough to this hull to paint it, that the sprayer is functional and that the color matches
|
||||
if (c.Character != null && c.Character.AllowInput && c.Character.SelectedItems.Any(it => it?.GetComponent<Sprayer>() != null))
|
||||
if (c.Character != null && c.Character.AllowInput && c.Character.HeldItems.Any(it => it.GetComponent<Sprayer>() != null))
|
||||
{
|
||||
BackgroundSections[i].SetColorStrength(colorStrength);
|
||||
BackgroundSections[i].SetColor(color);
|
||||
|
||||
@@ -320,7 +320,17 @@ namespace Barotrauma.Networking
|
||||
|
||||
outMsg.Write(bannedPlayer.Name);
|
||||
outMsg.Write(bannedPlayer.UniqueIdentifier);
|
||||
outMsg.Write(bannedPlayer.IsRangeBan); outMsg.WritePadBits();
|
||||
outMsg.Write(bannedPlayer.IsRangeBan);
|
||||
outMsg.Write(bannedPlayer.ExpirationTime != null);
|
||||
outMsg.WritePadBits();
|
||||
if (bannedPlayer.ExpirationTime != null)
|
||||
{
|
||||
double hoursFromNow = (bannedPlayer.ExpirationTime.Value - DateTime.Now).TotalHours;
|
||||
outMsg.Write(hoursFromNow);
|
||||
}
|
||||
|
||||
outMsg.Write(bannedPlayer.Reason ?? "");
|
||||
|
||||
if (c.Connection == GameMain.Server.OwnerConnection)
|
||||
{
|
||||
outMsg.Write(bannedPlayer.EndPoint);
|
||||
|
||||
@@ -25,7 +25,54 @@ namespace Barotrauma.Networking
|
||||
int orderIndex = msg.ReadByte();
|
||||
orderTargetCharacter = Entity.FindEntityByID(msg.ReadUInt16()) as Character;
|
||||
orderTargetEntity = Entity.FindEntityByID(msg.ReadUInt16()) as Entity;
|
||||
int orderOptionIndex = msg.ReadByte();
|
||||
|
||||
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)
|
||||
{
|
||||
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())
|
||||
{
|
||||
@@ -41,14 +88,14 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (orderIndex < 0 || orderIndex >= Order.PrefabList.Count)
|
||||
{
|
||||
DebugConsole.ThrowError($"Invalid order message from client \"{c.Name}\" - order index out of bounds ({orderIndex}, {orderOptionIndex}).");
|
||||
DebugConsole.ThrowError($"Invalid order message from client \"{c.Name}\" - order index out of bounds ({orderIndex}).");
|
||||
if (NetIdUtils.IdMoreRecent(ID, c.LastSentChatMsgID)) { c.LastSentChatMsgID = ID; }
|
||||
return;
|
||||
}
|
||||
|
||||
Order orderPrefab = Order.PrefabList[orderIndex];
|
||||
string orderOption = orderOptionIndex < 0 || orderOptionIndex >= orderPrefab.Options.Length ? "" : orderPrefab.Options[orderOptionIndex];
|
||||
orderMsg = new OrderChatMessage(orderPrefab, orderOption, orderTargetPosition ?? orderTargetEntity as ISpatialEntity, orderTargetCharacter, c.Character)
|
||||
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)
|
||||
{
|
||||
WallSectionIndex = wallSectionIndex
|
||||
};
|
||||
@@ -147,7 +194,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
if (order != null)
|
||||
{
|
||||
orderTargetCharacter.SetOrder(order, orderMsg.OrderOption, orderMsg.Sender);
|
||||
orderTargetCharacter.SetOrder(order, orderMsg.OrderOption, orderMsg.OrderPriority, orderMsg.Sender);
|
||||
}
|
||||
}
|
||||
else if (orderMsg.Order.IsIgnoreOrder)
|
||||
@@ -155,11 +202,17 @@ namespace Barotrauma.Networking
|
||||
switch (orderTargetType)
|
||||
{
|
||||
case Order.OrderTargetType.Entity:
|
||||
(orderTargetEntity as MapEntity)?.SetIgnoreByAI(orderMsg.Order.Identifier == "ignorethis");
|
||||
if (orderTargetEntity is IIgnorable ignorableEntity)
|
||||
{
|
||||
ignorableEntity.OrderedToBeIgnored = orderMsg.Order.Identifier == "ignorethis";
|
||||
}
|
||||
break;
|
||||
case Order.OrderTargetType.WallSection:
|
||||
if (!wallSectionIndex.HasValue) { break; }
|
||||
(orderTargetEntity as Structure)?.GetSection(wallSectionIndex.Value)?.SetIgnoreByAI(orderMsg.Order.Identifier == "ignorethis");
|
||||
if (orderTargetEntity is Structure s && s.GetSection(wallSectionIndex.Value) is IIgnorable ignorableWall)
|
||||
{
|
||||
ignorableWall.OrderedToBeIgnored = orderMsg.Order.Identifier == "ignorethis";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,10 +35,10 @@ namespace Barotrauma.Networking
|
||||
|
||||
public bool SubmarineSwitchLoad = false;
|
||||
|
||||
private List<Client> connectedClients = new List<Client>();
|
||||
private readonly List<Client> connectedClients = new List<Client>();
|
||||
|
||||
//for keeping track of disconnected clients in case the reconnect shortly after
|
||||
private List<Client> disconnectedClients = new List<Client>();
|
||||
private readonly List<Client> disconnectedClients = new List<Client>();
|
||||
|
||||
//keeps track of players who've previously been playing on the server
|
||||
//so kick votes persist during the session and the server can let the clients know what name this client used previously
|
||||
@@ -912,7 +912,10 @@ namespace Barotrauma.Networking
|
||||
errorLines.Add("Campaign ID: " + campaign.CampaignID);
|
||||
errorLines.Add("Campaign save ID: " + campaign.LastSaveID);
|
||||
}
|
||||
errorLines.Add("Mission: " + (GameMain.GameSession?.Mission?.Prefab.Identifier ?? "none"));
|
||||
foreach (Mission mission in GameMain.GameSession.Missions)
|
||||
{
|
||||
errorLines.Add("Mission: " + mission.Prefab.Identifier);
|
||||
}
|
||||
}
|
||||
if (GameMain.GameSession?.Submarine != null)
|
||||
{
|
||||
@@ -1247,22 +1250,27 @@ namespace Barotrauma.Networking
|
||||
bool range = inc.ReadBoolean();
|
||||
double durationSeconds = inc.ReadDouble();
|
||||
|
||||
TimeSpan? banDuration = null;
|
||||
if (durationSeconds > 0) { banDuration = TimeSpan.FromSeconds(durationSeconds); }
|
||||
|
||||
var bannedClient = connectedClients.Find(cl => cl != sender && cl.Name.Equals(bannedName, StringComparison.OrdinalIgnoreCase) && cl.Connection != OwnerConnection);
|
||||
if (bannedClient != null)
|
||||
{
|
||||
Log("Client \"" + ClientLogName(sender) + "\" banned \"" + ClientLogName(bannedClient) + "\".", ServerLog.MessageType.ServerMessage);
|
||||
if (durationSeconds > 0)
|
||||
{
|
||||
BanClient(bannedClient, string.IsNullOrEmpty(banReason) ? $"ServerMessage.BannedBy~[initiator]={sender.Name}" : banReason, range, TimeSpan.FromSeconds(durationSeconds));
|
||||
}
|
||||
else
|
||||
{
|
||||
BanClient(bannedClient, string.IsNullOrEmpty(banReason) ? $"ServerMessage.BannedBy~[initiator]={sender.Name}" : banReason, range);
|
||||
}
|
||||
BanClient(bannedClient, string.IsNullOrEmpty(banReason) ? $"ServerMessage.BannedBy~[initiator]={sender.Name}" : banReason, range, banDuration);
|
||||
}
|
||||
else
|
||||
{
|
||||
SendDirectChatMessage(TextManager.GetServerMessage($"ServerMessage.PlayerNotFound~[player]={bannedName}"), sender, ChatMessageType.Console);
|
||||
var bannedPreviousClient = previousPlayers.Find(p => p.Name.Equals(bannedName, StringComparison.OrdinalIgnoreCase));
|
||||
if (bannedPreviousClient != null)
|
||||
{
|
||||
Log("Client \"" + ClientLogName(sender) + "\" banned \"" + bannedPreviousClient.Name + "\".", ServerLog.MessageType.ServerMessage);
|
||||
BanPreviousPlayer(bannedPreviousClient, string.IsNullOrEmpty(banReason) ? $"ServerMessage.BannedBy~[initiator]={sender.Name}" : banReason, range, banDuration);
|
||||
}
|
||||
else
|
||||
{
|
||||
SendDirectChatMessage(TextManager.GetServerMessage($"ServerMessage.PlayerNotFound~[player]={bannedName}"), sender, ChatMessageType.Console);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ClientPermissions.Unban:
|
||||
@@ -1546,14 +1554,16 @@ namespace Barotrauma.Networking
|
||||
if (!character.Enabled) { continue; }
|
||||
if (c.SpectatePos == null)
|
||||
{
|
||||
if (c.Character != null && Vector2.DistanceSquared(character.WorldPosition, c.Character.WorldPosition) >= NetConfig.DisableCharacterDistSqr)
|
||||
float distSqr = Vector2.DistanceSquared(character.WorldPosition, c.Character.WorldPosition);
|
||||
if (c.Character.ViewTarget != null)
|
||||
{
|
||||
continue;
|
||||
distSqr = Math.Min(distSqr, Vector2.DistanceSquared(character.WorldPosition, c.Character.ViewTarget.WorldPosition));
|
||||
}
|
||||
if (distSqr >= MathUtils.Pow2(character.Params.DisableDistance)) { continue; }
|
||||
}
|
||||
else
|
||||
{
|
||||
if (character != c.Character && Vector2.DistanceSquared(character.WorldPosition, c.SpectatePos.Value) >= NetConfig.DisableCharacterDistSqr)
|
||||
if (character != c.Character && Vector2.DistanceSquared(character.WorldPosition, c.SpectatePos.Value) >= MathUtils.Pow2(character.Params.DisableDistance))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -1644,6 +1654,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
IWriteMessage tempBuffer = new ReadWriteMessage();
|
||||
tempBuffer.Write((byte)ServerNetObject.ENTITY_POSITION);
|
||||
tempBuffer.Write(entity is Item);
|
||||
if (entity is Item)
|
||||
{
|
||||
((Item)entity).ServerWritePosition(tempBuffer, c);
|
||||
@@ -1740,6 +1751,7 @@ namespace Barotrauma.Networking
|
||||
outmsg.Write(client.NameID);
|
||||
outmsg.Write(client.Name);
|
||||
outmsg.Write(client.Character?.Info?.Job != null && gameStarted ? client.Character.Info.Job.Prefab.Identifier : (client.PreferredJob ?? ""));
|
||||
outmsg.Write((byte)client.PreferredTeam);
|
||||
outmsg.Write(client.Character == null || !gameStarted ? (ushort)0 : client.Character.ID);
|
||||
if (c.HasPermission(ClientPermissions.ServerLog))
|
||||
{
|
||||
@@ -2066,14 +2078,14 @@ namespace Barotrauma.Networking
|
||||
//always allow the server owner to spectate even if it's disallowed in server settings
|
||||
playingClients.RemoveAll(c => c.Connection == OwnerConnection && c.SpectateOnly);
|
||||
|
||||
if (GameMain.GameSession.GameMode.Mission != null)
|
||||
if (GameMain.GameSession.GameMode is PvPMode pvpMode)
|
||||
{
|
||||
GameMain.GameSession.GameMode.Mission.AssignTeamIDs(playingClients);
|
||||
teamCount = GameMain.GameSession.GameMode.Mission.TeamCount;
|
||||
pvpMode.AssignTeamIDs(playingClients);
|
||||
teamCount = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
connectedClients.ForEach(c => c.TeamID = Character.TeamType.Team1);
|
||||
connectedClients.ForEach(c => c.TeamID = CharacterTeamType.Team1);
|
||||
}
|
||||
|
||||
if (campaign != null)
|
||||
@@ -2101,7 +2113,6 @@ namespace Barotrauma.Networking
|
||||
Log("Game mode: " + selectedMode.Name, ServerLog.MessageType.ServerMessage);
|
||||
Log("Submarine: " + GameMain.GameSession.SubmarineInfo.Name, ServerLog.MessageType.ServerMessage);
|
||||
Log("Level seed: " + campaign.NextLevel.Seed, ServerLog.MessageType.ServerMessage);
|
||||
if (GameMain.GameSession.Mission != null) { Log("Mission: " + GameMain.GameSession.Mission.Prefab.Name, ServerLog.MessageType.ServerMessage); }
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2111,7 +2122,11 @@ namespace Barotrauma.Networking
|
||||
Log("Game mode: " + selectedMode.Name, ServerLog.MessageType.ServerMessage);
|
||||
Log("Submarine: " + selectedSub.Name, ServerLog.MessageType.ServerMessage);
|
||||
Log("Level seed: " + GameMain.NetLobbyScreen.LevelSeed, ServerLog.MessageType.ServerMessage);
|
||||
if (GameMain.GameSession.Mission != null) { Log("Mission: " + GameMain.GameSession.Mission.Prefab.Name, ServerLog.MessageType.ServerMessage); }
|
||||
}
|
||||
|
||||
foreach (Mission mission in GameMain.GameSession.Missions)
|
||||
{
|
||||
Log("Mission: " + mission.Prefab.Name, ServerLog.MessageType.ServerMessage);
|
||||
}
|
||||
|
||||
if (GameMain.GameSession.SubmarineInfo.IsFileCorrupted)
|
||||
@@ -2123,7 +2138,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
MissionMode missionMode = GameMain.GameSession.GameMode as MissionMode;
|
||||
bool missionAllowRespawn = GameMain.GameSession.Campaign == null && (missionMode?.Mission == null || missionMode.Mission.AllowRespawn);
|
||||
bool missionAllowRespawn = GameMain.GameSession.Campaign == null && (missionMode == null || !missionMode.Missions.Any(m => !m.AllowRespawn));
|
||||
bool outpostAllowRespawn = GameMain.GameSession.Campaign != null && Level.Loaded?.Type == LevelData.LevelType.Outpost;
|
||||
|
||||
if (serverSettings.AllowRespawn && (missionAllowRespawn || outpostAllowRespawn))
|
||||
@@ -2145,7 +2160,7 @@ namespace Barotrauma.Networking
|
||||
//assign jobs and spawnpoints separately for each team
|
||||
for (int n = 0; n < teamCount; n++)
|
||||
{
|
||||
var teamID = n == 0 ? Character.TeamType.Team1 : Character.TeamType.Team2;
|
||||
var teamID = n == 0 ? CharacterTeamType.Team1 : CharacterTeamType.Team2;
|
||||
|
||||
Submarine.MainSubs[n].TeamID = teamID;
|
||||
foreach (Item item in Item.ItemList)
|
||||
@@ -2172,7 +2187,7 @@ namespace Barotrauma.Networking
|
||||
//always allow the server owner to spectate even if it's disallowed in server settings
|
||||
teamClients.RemoveAll(c => c.Connection == OwnerConnection && c.SpectateOnly);
|
||||
|
||||
if (!teamClients.Any() && n > 0) { continue; }
|
||||
//if (!teamClients.Any() && n > 0) { continue; }
|
||||
|
||||
AssignJobs(teamClients);
|
||||
|
||||
@@ -2191,6 +2206,10 @@ 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)
|
||||
{
|
||||
@@ -2232,7 +2251,9 @@ namespace Barotrauma.Networking
|
||||
|
||||
List<WayPoint> spawnWaypoints = null;
|
||||
List<WayPoint> mainSubWaypoints = WayPoint.SelectCrewSpawnPoints(characterInfos, Submarine.MainSubs[n]).ToList();
|
||||
if (Level.Loaded?.StartOutpost != null && Level.Loaded.Type == LevelData.LevelType.Outpost &&
|
||||
if (Level.Loaded?.StartOutpost != null &&
|
||||
Level.Loaded.Type == LevelData.LevelType.Outpost &&
|
||||
(Level.Loaded.StartOutpost.Info.OutpostGenerationParams?.SpawnCrewInsideOutpost ?? false) &&
|
||||
Level.Loaded.StartOutpost.GetConnectedSubs().Any(s => s.Info.Type == SubmarineType.Player))
|
||||
{
|
||||
spawnWaypoints = WayPoint.WayPointList.FindAll(wp =>
|
||||
@@ -2291,16 +2312,25 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
if (crewManager != null && crewManager.HasBots && hadBots)
|
||||
if (crewManager != null && crewManager.HasBots)
|
||||
{
|
||||
crewManager?.InitRound();
|
||||
if (hadBots)
|
||||
{
|
||||
//loaded existing bots -> init them
|
||||
crewManager?.InitRound();
|
||||
}
|
||||
else
|
||||
{
|
||||
//created new bots -> save them
|
||||
SaveUtil.SaveGame(GameMain.GameSession.SavePath);
|
||||
}
|
||||
}
|
||||
|
||||
campaign?.LoadPets();
|
||||
|
||||
foreach (Submarine sub in Submarine.MainSubs)
|
||||
{
|
||||
if (sub == null) continue;
|
||||
if (sub == null) { continue; }
|
||||
|
||||
List<PurchasedItem> spawnList = new List<PurchasedItem>();
|
||||
foreach (KeyValuePair<ItemPrefab, int> kvp in serverSettings.ExtraCargo)
|
||||
@@ -2308,7 +2338,7 @@ namespace Barotrauma.Networking
|
||||
spawnList.Add(new PurchasedItem(kvp.Key, kvp.Value));
|
||||
}
|
||||
|
||||
CargoManager.CreateItems(spawnList);
|
||||
CargoManager.CreateItems(spawnList, sub);
|
||||
}
|
||||
|
||||
TraitorManager = null;
|
||||
@@ -2363,8 +2393,7 @@ namespace Barotrauma.Networking
|
||||
msg.Write((byte)ServerPacketHeader.STARTGAME);
|
||||
msg.Write(seed);
|
||||
msg.Write(gameSession.GameMode.Preset.Identifier);
|
||||
|
||||
bool missionAllowRespawn = campaign == null && (missionMode?.Mission == null || missionMode.Mission.AllowRespawn);
|
||||
bool missionAllowRespawn = campaign == null && (missionMode == null || !missionMode.Missions.Any(m => !m.AllowRespawn));
|
||||
bool outpostAllowRespawn = campaign != null && campaign.NextLevel?.Type == LevelData.LevelType.Outpost;
|
||||
msg.Write(serverSettings.AllowRespawn && (missionAllowRespawn || outpostAllowRespawn));
|
||||
msg.Write(serverSettings.AllowDisguises);
|
||||
@@ -2384,7 +2413,11 @@ namespace Barotrauma.Networking
|
||||
msg.Write(gameSession.SubmarineInfo.MD5Hash.Hash);
|
||||
msg.Write(GameMain.NetLobbyScreen.SelectedShuttle.Name);
|
||||
msg.Write(GameMain.NetLobbyScreen.SelectedShuttle.MD5Hash.Hash);
|
||||
msg.Write((short)(GameMain.GameSession.GameMode?.Mission == null ? -1 : MissionPrefab.List.IndexOf(GameMain.GameSession.GameMode.Mission.Prefab)));
|
||||
msg.Write((byte)GameMain.GameSession.GameMode.Missions.Count());
|
||||
foreach (Mission mission in GameMain.GameSession.GameMode.Missions)
|
||||
{
|
||||
msg.Write((short)MissionPrefab.List.IndexOf(mission.Prefab));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2424,13 +2457,20 @@ namespace Barotrauma.Networking
|
||||
msg.Write(contentFile.Path);
|
||||
}
|
||||
msg.Write(Submarine.MainSub?.Info.EqualityCheckVal ?? 0);
|
||||
msg.Write(GameMain.GameSession.Mission?.Prefab.Identifier ?? "");
|
||||
msg.Write((byte)GameMain.GameSession.Missions.Count());
|
||||
foreach (Mission mission in GameMain.GameSession.Missions)
|
||||
{
|
||||
msg.Write(mission.Prefab.Identifier);
|
||||
}
|
||||
msg.Write((byte)GameMain.GameSession.Level.EqualityCheckValues.Count);
|
||||
foreach (int equalityCheckValue in GameMain.GameSession.Level.EqualityCheckValues)
|
||||
{
|
||||
msg.Write(equalityCheckValue);
|
||||
}
|
||||
GameMain.GameSession.Mission?.ServerWriteInitial(msg, client);
|
||||
foreach (Mission mission in GameMain.GameSession.Missions)
|
||||
{
|
||||
mission.ServerWriteInitial(msg, client);
|
||||
}
|
||||
}
|
||||
|
||||
public void EndGame(CampaignMode.TransitionType transitionType = CampaignMode.TransitionType.None)
|
||||
@@ -2453,7 +2493,7 @@ namespace Barotrauma.Networking
|
||||
string endMessage = TextManager.FormatServerMessage("RoundSummaryRoundHasEnded");
|
||||
var traitorResults = TraitorManager?.GetEndResults() ?? new List<TraitorMissionResult>();
|
||||
|
||||
Mission mission = GameMain.GameSession.Mission;
|
||||
List<Mission> missions = GameMain.GameSession.Missions.ToList();
|
||||
if (GameMain.GameSession.IsRunning)
|
||||
{
|
||||
GameMain.GameSession.EndRound(endMessage, traitorResults);
|
||||
@@ -2495,7 +2535,11 @@ namespace Barotrauma.Networking
|
||||
msg.Write((byte)ServerPacketHeader.ENDGAME);
|
||||
msg.Write((byte)transitionType);
|
||||
msg.Write(endMessage);
|
||||
msg.Write(mission != null && mission.Completed);
|
||||
msg.Write((byte)missions.Count);
|
||||
foreach (Mission mission in missions)
|
||||
{
|
||||
msg.Write(mission.Completed);
|
||||
}
|
||||
msg.Write(GameMain.GameSession?.WinningTeam == null ? (byte)0 : (byte)GameMain.GameSession.WinningTeam);
|
||||
|
||||
msg.Write((byte)traitorResults.Count);
|
||||
@@ -2507,6 +2551,7 @@ namespace Barotrauma.Networking
|
||||
foreach (Client client in connectedClients)
|
||||
{
|
||||
serverPeer.Send(msg, client.Connection, DeliveryMethod.Reliable);
|
||||
client.Character?.Info?.ClearCurrentOrders();
|
||||
client.Character = null;
|
||||
client.HasSpawned = false;
|
||||
client.InGame = false;
|
||||
@@ -2543,13 +2588,15 @@ namespace Barotrauma.Networking
|
||||
UInt16 nameId = inc.ReadUInt16();
|
||||
string newName = inc.ReadString();
|
||||
string newJob = inc.ReadString();
|
||||
CharacterTeamType newTeam = (CharacterTeamType)inc.ReadByte();
|
||||
|
||||
if (c == null || string.IsNullOrEmpty(newName) || !NetIdUtils.IdMoreRecent(nameId, c.NameID)) { return false; }
|
||||
|
||||
c.NameID = nameId;
|
||||
newName = Client.SanitizeName(newName);
|
||||
if (newName == c.Name && newJob == c.PreferredJob) { return false; }
|
||||
if (newName == c.Name && newJob == c.PreferredJob && newTeam == c.PreferredTeam) { return false; }
|
||||
c.PreferredJob = newJob;
|
||||
c.PreferredTeam = newTeam;
|
||||
|
||||
//update client list even if the name cannot be changed to the one sent by the client,
|
||||
//so the client will be informed what their actual name is
|
||||
@@ -2663,7 +2710,6 @@ namespace Barotrauma.Networking
|
||||
lidgrenConn.IPEndPoint.Address.MapToIPv4NoThrow().ToString() :
|
||||
lidgrenConn.IPEndPoint.Address.ToString();
|
||||
if (range) { ip = BanList.ToRange(ip); }
|
||||
|
||||
serverSettings.BanList.BanPlayer(client.Name, ip, reason, duration);
|
||||
}
|
||||
if (client.SteamID > 0)
|
||||
@@ -2672,6 +2718,32 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
public void BanPreviousPlayer(PreviousPlayer previousPlayer, string reason, bool range = false, TimeSpan? duration = null)
|
||||
{
|
||||
if (previousPlayer == null) { return; }
|
||||
|
||||
//reset karma to a neutral value, so if/when the ban is revoked the client wont get immediately punished by low karma again
|
||||
previousPlayer.Karma = Math.Max(previousPlayer.Karma, 50.0f);
|
||||
|
||||
if (!string.IsNullOrEmpty(previousPlayer.EndPoint) && (previousPlayer.SteamID == 0 || range))
|
||||
{
|
||||
string ip = previousPlayer.EndPoint;
|
||||
if (range) { ip = BanList.ToRange(ip); }
|
||||
serverSettings.BanList.BanPlayer(previousPlayer.Name, ip, reason, duration);
|
||||
}
|
||||
if (previousPlayer.SteamID > 0)
|
||||
{
|
||||
serverSettings.BanList.BanPlayer(previousPlayer.Name, previousPlayer.SteamID, reason, duration);
|
||||
}
|
||||
|
||||
string msg = $"ServerMessage.BannedFromServer~[client]={previousPlayer.Name}";
|
||||
if (!string.IsNullOrWhiteSpace(reason))
|
||||
{
|
||||
msg += $"/ /ServerMessage.Reason/: /{reason}";
|
||||
}
|
||||
SendChatMessage(msg, ChatMessageType.Server, changeType: PlayerConnectionChangeType.Banned);
|
||||
}
|
||||
|
||||
public override void UnbanPlayer(string playerName, string playerEndPoint)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(playerEndPoint))
|
||||
@@ -2712,8 +2784,8 @@ namespace Barotrauma.Networking
|
||||
client.HasSpawned = false;
|
||||
client.InGame = false;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(msg)) msg = $"ServerMessage.ClientLeftServer~[client]={client.Name}";
|
||||
if (string.IsNullOrWhiteSpace(targetmsg)) targetmsg = "ServerMessage.YouLeftServer";
|
||||
if (string.IsNullOrWhiteSpace(msg)) { msg = $"ServerMessage.ClientLeftServer~[client]={client.Name}"; }
|
||||
if (string.IsNullOrWhiteSpace(targetmsg)) { targetmsg = "ServerMessage.YouLeftServer"; }
|
||||
if (!string.IsNullOrWhiteSpace(reason))
|
||||
{
|
||||
msg += $"/ /ServerMessage.Reason/: /{reason}";
|
||||
@@ -2923,14 +2995,14 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
case ChatMessageType.Radio:
|
||||
case ChatMessageType.Order:
|
||||
if (senderCharacter == null) return;
|
||||
if (senderCharacter == null) { return; }
|
||||
|
||||
//return if senderCharacter doesn't have a working radio
|
||||
var radio = senderCharacter.Inventory?.Items.FirstOrDefault(i => i != null && i.GetComponent<WifiComponent>() != null);
|
||||
if (radio == null || !senderCharacter.HasEquippedItem(radio)) return;
|
||||
var radio = senderCharacter.Inventory?.AllItems.FirstOrDefault(i => i.GetComponent<WifiComponent>() != null);
|
||||
if (radio == null || !senderCharacter.HasEquippedItem(radio)) { return; }
|
||||
|
||||
senderRadio = radio.GetComponent<WifiComponent>();
|
||||
if (!senderRadio.CanTransmit()) return;
|
||||
if (!senderRadio.CanTransmit()) { return; }
|
||||
break;
|
||||
case ChatMessageType.Dead:
|
||||
//character still alive and capable of speaking -> dead chat not allowed
|
||||
@@ -2949,7 +3021,7 @@ namespace Barotrauma.Networking
|
||||
else if (type == ChatMessageType.Radio)
|
||||
{
|
||||
//send to chat-linked wifi components
|
||||
senderRadio.TransmitSignal(0, message, senderRadio.Item, senderCharacter, false);
|
||||
senderRadio.TransmitSignal(0, message, senderRadio.Item, senderCharacter, sentFromChat: true);
|
||||
}
|
||||
|
||||
//check which clients can receive the message and apply distance effects
|
||||
@@ -3022,14 +3094,14 @@ namespace Barotrauma.Networking
|
||||
if (!client.Character.CanHearCharacter(message.Sender)) { continue; }
|
||||
}
|
||||
|
||||
SendDirectChatMessage(new OrderChatMessage(message.Order, message.OrderOption, message.TargetEntity, message.TargetCharacter, message.Sender), client);
|
||||
SendDirectChatMessage(new OrderChatMessage(message.Order, message.OrderOption, message.OrderPriority, message.TargetEntity, message.TargetCharacter, message.Sender), client);
|
||||
}
|
||||
|
||||
string myReceivedMessage = message.Text;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(myReceivedMessage))
|
||||
{
|
||||
AddChatMessage(new OrderChatMessage(message.Order, message.OrderOption, myReceivedMessage, message.TargetEntity, message.TargetCharacter, message.Sender));
|
||||
AddChatMessage(new OrderChatMessage(message.Order, message.OrderOption, message.OrderPriority, myReceivedMessage, message.TargetEntity, message.TargetCharacter, message.Sender));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3145,8 +3217,8 @@ namespace Barotrauma.Networking
|
||||
|
||||
if (voteType != VoteType.PurchaseSub)
|
||||
{
|
||||
GameMain.GameSession.SwitchSubmarine(targetSubmarine, deliveryFee);
|
||||
GameMain.GameSession.Campaign.UpgradeManager.RefundResetAndReload(targetSubmarine, true);
|
||||
SubmarineInfo newSub = GameMain.GameSession.SwitchSubmarine(targetSubmarine, deliveryFee);
|
||||
GameMain.GameSession.Campaign.UpgradeManager.RefundResetAndReload(newSub, true);
|
||||
}
|
||||
|
||||
serverSettings.Voting.StopSubmarineVote(true);
|
||||
@@ -3374,7 +3446,7 @@ namespace Barotrauma.Networking
|
||||
assignedClientCount.Add(jp, 0);
|
||||
}
|
||||
|
||||
Character.TeamType teamID = Character.TeamType.None;
|
||||
CharacterTeamType teamID = CharacterTeamType.None;
|
||||
if (unassigned.Count > 0) { teamID = unassigned[0].TeamID; }
|
||||
|
||||
//if we're playing a multiplayer campaign, check which clients already have a character and a job
|
||||
@@ -3411,9 +3483,9 @@ namespace Barotrauma.Networking
|
||||
unassigned.RemoveAt(i);
|
||||
}
|
||||
|
||||
//go throught the jobs whose MinNumber>0 (i.e. at least one crew member has to have the job)
|
||||
// Assign the necessary jobs that are always required at least one, in vanilla this means in practice the captain
|
||||
bool unassignedJobsFound = true;
|
||||
while (unassignedJobsFound && unassigned.Count > 0)
|
||||
while (unassignedJobsFound && unassigned.Any())
|
||||
{
|
||||
unassignedJobsFound = false;
|
||||
|
||||
@@ -3421,16 +3493,33 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (unassigned.Count == 0) { break; }
|
||||
if (jobPrefab.MinNumber < 1 || assignedClientCount[jobPrefab] >= jobPrefab.MinNumber) { continue; }
|
||||
// Find the client that wants the job the most, don't force any jobs yet, because it might be that we can meet the preference for other jobs.
|
||||
Client client = FindClientWithJobPreference(unassigned, jobPrefab, forceAssign: false);
|
||||
if (client != null)
|
||||
{
|
||||
AssignJob(client, jobPrefab);
|
||||
}
|
||||
}
|
||||
|
||||
//find the client that wants the job the most, or force it to random client if none of them want it
|
||||
Client assignedClient = FindClientWithJobPreference(unassigned, jobPrefab, true);
|
||||
if (unassigned.Any())
|
||||
{
|
||||
// Another pass, force required jobs that are not yet filled.
|
||||
foreach (JobPrefab jobPrefab in jobList)
|
||||
{
|
||||
if (unassigned.Count == 0) { break; }
|
||||
if (jobPrefab.MinNumber < 1 || assignedClientCount[jobPrefab] >= jobPrefab.MinNumber) { continue; }
|
||||
AssignJob(FindClientWithJobPreference(unassigned, jobPrefab, forceAssign: true), jobPrefab);
|
||||
}
|
||||
}
|
||||
|
||||
assignedClient.AssignedJob =
|
||||
assignedClient.JobPreferences.FirstOrDefault(jp => jp.First == jobPrefab) ??
|
||||
new Pair<JobPrefab, int>(jobPrefab, 0);
|
||||
void AssignJob(Client client, JobPrefab jobPrefab)
|
||||
{
|
||||
client.AssignedJob =
|
||||
client.JobPreferences.FirstOrDefault(jp => jp.First == jobPrefab) ??
|
||||
new Pair<JobPrefab, int>(jobPrefab, Rand.Int(jobPrefab.Variants));
|
||||
|
||||
assignedClientCount[jobPrefab]++;
|
||||
unassigned.Remove(assignedClient);
|
||||
unassigned.Remove(client);
|
||||
|
||||
//the job still needs more crew members, set unassignedJobsFound to true to keep the while loop running
|
||||
if (assignedClientCount[jobPrefab] < jobPrefab.MinNumber) { unassignedJobsFound = true; }
|
||||
@@ -3464,32 +3553,37 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
} while (unassigned.Count > 0 && canAssign);*/
|
||||
|
||||
//attempt to give the clients a job they have in their job preferences
|
||||
for (int i = unassigned.Count - 1; i >= 0; i--)
|
||||
// Attempt to give the clients a job they have in their job preferences.
|
||||
// First evaluate all the primary preferences, then all the secondary etc.
|
||||
for (int preferenceIndex = 0; preferenceIndex < 3; preferenceIndex++)
|
||||
{
|
||||
if (unassignedSpawnPoints.Count == 0) { break; }
|
||||
foreach (Pair<JobPrefab, int> preferredJob in unassigned[i].JobPreferences)
|
||||
if (unassignedSpawnPoints.None()) { break; }
|
||||
for (int i = unassigned.Count - 1; i >= 0; i--)
|
||||
{
|
||||
//can't assign this job if maximum number has reached or the clien't karma is too low
|
||||
if (assignedClientCount[preferredJob.First] >= preferredJob.First.MaxNumber || unassigned[i].Karma < preferredJob.First.MinKarma)
|
||||
if (unassignedSpawnPoints.None()) { break; }
|
||||
Client client = unassigned[i];
|
||||
if (preferenceIndex >= client.JobPreferences.Count) { continue; }
|
||||
var preferredJob = client.JobPreferences[preferenceIndex];
|
||||
JobPrefab jobPrefab = preferredJob.First;
|
||||
if (assignedClientCount[jobPrefab] >= jobPrefab.MaxNumber || client.Karma < jobPrefab.MinKarma)
|
||||
{
|
||||
//can't assign this job if maximum number has reached or the clien't karma is too low
|
||||
continue;
|
||||
}
|
||||
//give the client their preferred job if there's a spawnpoint available for that job
|
||||
var matchingSpawnPoint = unassignedSpawnPoints.Find(s => s.AssignedJob == preferredJob.First);
|
||||
//if the job is not available in any spawnpoint (custom job?), treat empty spawnpoints
|
||||
//as a matching ones
|
||||
if (matchingSpawnPoint == null && !availableSpawnPoints.Any(s => s.AssignedJob == preferredJob.First))
|
||||
var matchingSpawnPoint = unassignedSpawnPoints.Find(s => s.AssignedJob == jobPrefab);
|
||||
if (matchingSpawnPoint == null && !availableSpawnPoints.Any(s => s.AssignedJob == jobPrefab))
|
||||
{
|
||||
//if the job is not available in any spawnpoint (custom job?), treat empty spawnpoints
|
||||
//as a matching ones
|
||||
matchingSpawnPoint = unassignedSpawnPoints.Find(s => s.AssignedJob == null);
|
||||
}
|
||||
if (matchingSpawnPoint != null)
|
||||
{
|
||||
unassignedSpawnPoints.Remove(matchingSpawnPoint);
|
||||
unassigned[i].AssignedJob = preferredJob;
|
||||
assignedClientCount[preferredJob.First]++;
|
||||
client.AssignedJob = preferredJob;
|
||||
assignedClientCount[jobPrefab]++;
|
||||
unassigned.RemoveAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3536,7 +3630,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
public void AssignBotJobs(List<CharacterInfo> bots, Character.TeamType teamID)
|
||||
public void AssignBotJobs(List<CharacterInfo> bots, CharacterTeamType teamID)
|
||||
{
|
||||
Dictionary<JobPrefab, int> assignedPlayerCount = new Dictionary<JobPrefab, int>();
|
||||
foreach (JobPrefab jp in JobPrefab.Prefabs)
|
||||
@@ -3614,11 +3708,9 @@ namespace Barotrauma.Networking
|
||||
Client preferredClient = null;
|
||||
foreach (Client c in clients)
|
||||
{
|
||||
if (c.Karma < job.MinKarma) continue;
|
||||
if (c.Karma < job.MinKarma) { continue; }
|
||||
int index = c.JobPreferences.IndexOf(c.JobPreferences.Find(j => j.First == job));
|
||||
if (index == -1) index = 1000;
|
||||
|
||||
if (preferredClient == null || index < bestPreference)
|
||||
if (index > -1 && index < bestPreference)
|
||||
{
|
||||
bestPreference = index;
|
||||
preferredClient = c;
|
||||
@@ -3634,12 +3726,14 @@ namespace Barotrauma.Networking
|
||||
return preferredClient;
|
||||
}
|
||||
|
||||
public void UpdateMissionState(int state)
|
||||
public void UpdateMissionState(Mission mission, int state)
|
||||
{
|
||||
foreach (var client in connectedClients)
|
||||
{
|
||||
IWriteMessage msg = new WriteOnlyMessage();
|
||||
msg.Write((byte)ServerPacketHeader.MISSION);
|
||||
int missionIndex = GameMain.GameSession.GetMissionIndex(mission);
|
||||
msg.Write((byte)(missionIndex == -1 ? 255: missionIndex));
|
||||
msg.Write((ushort)state);
|
||||
serverPeer.Send(msg, client.Connection, DeliveryMethod.Reliable);
|
||||
}
|
||||
@@ -3653,7 +3747,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
retVal += "color:#ff9900;";
|
||||
}
|
||||
retVal += "metadata:" + (client.SteamID!=0 ? client.SteamID.ToString() : client.ID.ToString()) + "‖" + (name ?? client.Name) + "‖end‖";
|
||||
retVal += "metadata:" + (client.SteamID != 0 ? client.SteamID.ToString() : client.ID.ToString()) + "‖" + (name ?? client.Name) + "‖end‖";
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
@@ -256,8 +256,28 @@ namespace Barotrauma
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var foundItem = Inventory.FindItemRecursive(item, it => it.Prefab.Identifier == "idcard" || it.GetComponent<RangedWeapon>() != null || it.GetComponent<MeleeWeapon>() != null);
|
||||
|
||||
Item foundItem = null;
|
||||
if (isValid(item))
|
||||
{
|
||||
foundItem = item;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (Item containedItem in item.ContainedItems)
|
||||
{
|
||||
if (isValid(containedItem))
|
||||
{
|
||||
foundItem = containedItem;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool isValid(Item item)
|
||||
{
|
||||
return item.Prefab.Identifier == "idcard" || item.GetComponent<RangedWeapon>() != null || item.GetComponent<MeleeWeapon>() != null;
|
||||
}
|
||||
|
||||
if (foundItem == null) { return; }
|
||||
|
||||
@@ -382,7 +402,7 @@ namespace Barotrauma
|
||||
//smaller karma penalty for attacking someone who's aiming with a weapon
|
||||
if (damage > 0.0f &&
|
||||
target.IsKeyDown(InputType.Aim) &&
|
||||
target.SelectedItems.Any(it => it != null && (it.GetComponent<MeleeWeapon>() != null || it.GetComponent<RangedWeapon>() != null)))
|
||||
target.HeldItems.Any(it => it.GetComponent<MeleeWeapon>() != null || it.GetComponent<RangedWeapon>() != null))
|
||||
{
|
||||
damage *= 0.5f;
|
||||
stun *= 0.5f;
|
||||
@@ -473,12 +493,12 @@ namespace Barotrauma
|
||||
{
|
||||
//cap the damage so the karma can't decrease by more than MaxStructureDamageKarmaDecreasePerSecond per second
|
||||
var clientMemory = GetClientMemory(client);
|
||||
clientMemory.StructureDamageAccumulator += damageAmount;
|
||||
if (clientMemory.StructureDamagePerSecond + damageAmount >= MaxStructureDamageKarmaDecreasePerSecond / StructureDamageKarmaDecrease)
|
||||
{
|
||||
damageAmount -= (MaxStructureDamageKarmaDecreasePerSecond / StructureDamageKarmaDecrease) - clientMemory.StructureDamagePerSecond;
|
||||
damageAmount -= (clientMemory.StructureDamagePerSecond + damageAmount) - (MaxStructureDamageKarmaDecreasePerSecond / StructureDamageKarmaDecrease);
|
||||
if (damageAmount <= 0.0f) { return; }
|
||||
}
|
||||
clientMemory.StructureDamageAccumulator += damageAmount;
|
||||
}
|
||||
AdjustKarma(attacker, -damageAmount * StructureDamageKarmaDecrease, "Damaged structures");
|
||||
}
|
||||
|
||||
+2
-2
@@ -490,7 +490,7 @@ namespace Barotrauma.Networking
|
||||
continue;
|
||||
}
|
||||
|
||||
byte msgLength = msg.ReadByte();
|
||||
int msgLength = (int)msg.ReadVariableUInt32();
|
||||
|
||||
IClientSerializable entity = Entity.FindEntityByID(entityID) as IClientSerializable;
|
||||
|
||||
@@ -499,7 +499,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (GameSettings.VerboseLogging)
|
||||
{
|
||||
DebugConsole.NewMessage("Received msg " + thisEventID, Color.Red);
|
||||
DebugConsole.NewMessage("Received msg " + thisEventID + ", expecting " + sender.LastSentEntityEventID, Color.Red);
|
||||
}
|
||||
msg.BitPosition += msgLength * 8;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
|
||||
namespace Barotrauma.Networking
|
||||
namespace Barotrauma.Networking
|
||||
{
|
||||
partial class OrderChatMessage : ChatMessage
|
||||
{
|
||||
@@ -9,34 +7,13 @@ namespace Barotrauma.Networking
|
||||
msg.Write((byte)ServerNetObject.CHAT_MESSAGE);
|
||||
msg.Write(NetStateID);
|
||||
msg.Write((byte)ChatMessageType.Order);
|
||||
|
||||
msg.Write(SenderName);
|
||||
msg.Write(Sender != null && c.InGame);
|
||||
if (Sender != null && c.InGame)
|
||||
{
|
||||
msg.Write(Sender.ID);
|
||||
}
|
||||
|
||||
msg.Write((byte)Order.PrefabList.IndexOf(Order.Prefab));
|
||||
msg.Write(TargetCharacter == null ? (UInt16)0 : TargetCharacter.ID);
|
||||
msg.Write(TargetEntity is Entity ? (TargetEntity as Entity).ID : (UInt16)0);
|
||||
msg.Write((byte)Array.IndexOf(Order.Prefab.Options, OrderOption));
|
||||
msg.Write((byte)Order.TargetType);
|
||||
if (Order.TargetType == Order.OrderTargetType.Position && TargetEntity is OrderTarget orderTarget)
|
||||
{
|
||||
msg.Write(true);
|
||||
msg.Write(orderTarget.Position.X);
|
||||
msg.Write(orderTarget.Position.Y);
|
||||
msg.Write(orderTarget.Hull == null ? (UInt16)0 : orderTarget.Hull.ID);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg.Write(false);
|
||||
if (Order.TargetType == Order.OrderTargetType.WallSection)
|
||||
{
|
||||
msg.Write((byte)(WallSectionIndex ?? Order.WallSectionIndex ?? 0));
|
||||
}
|
||||
}
|
||||
WriteOrder(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
-1
@@ -39,7 +39,16 @@ namespace Barotrauma.Networking
|
||||
public double UpdateTime;
|
||||
public double TimeOut;
|
||||
public int Retries;
|
||||
public UInt64? SteamID;
|
||||
private UInt64? steamId;
|
||||
public UInt64? SteamID
|
||||
{
|
||||
get { return steamId; }
|
||||
set
|
||||
{
|
||||
steamId = value;
|
||||
Connection.SetSteamIDIfUnknown(value ?? 0);
|
||||
}
|
||||
}
|
||||
public Int32? PasswordSalt;
|
||||
public bool AuthSessionStarted;
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Barotrauma.Networking
|
||||
if (GameMain.Server.ServerSettings.BotSpawnMode == BotSpawnMode.Normal)
|
||||
{
|
||||
return Character.CharacterList
|
||||
.FindAll(c => c.TeamID == Character.TeamType.Team1 && c.AIController != null && c.Info != null && c.IsDead)
|
||||
.FindAll(c => c.TeamID == CharacterTeamType.Team1 && c.AIController != null && c.Info != null && c.IsDead)
|
||||
.Select(c => c.Info)
|
||||
.ToList();
|
||||
}
|
||||
@@ -46,7 +46,7 @@ namespace Barotrauma.Networking
|
||||
(!c.SpectateOnly || (!GameMain.Server.ServerSettings.AllowSpectating && GameMain.Server.OwnerConnection != c.Connection)));
|
||||
|
||||
var existingBots = Character.CharacterList
|
||||
.FindAll(c => c.TeamID == Character.TeamType.Team1 && c.AIController != null && c.Info != null);
|
||||
.FindAll(c => c.TeamID == CharacterTeamType.Team1 && c.AIController != null && c.Info != null);
|
||||
|
||||
int requiredBots = GameMain.Server.ServerSettings.BotCount - currPlayerCount;
|
||||
requiredBots -= existingBots.Count(b => !b.IsDead);
|
||||
@@ -238,13 +238,17 @@ namespace Barotrauma.Networking
|
||||
|
||||
//all characters are in Team 1 in game modes/missions with only one team.
|
||||
//if at some point we add a game mode with multiple teams where respawning is possible, this needs to be reworked
|
||||
c.TeamID = Character.TeamType.Team1;
|
||||
c.TeamID = CharacterTeamType.Team1;
|
||||
if (c.CharacterInfo == null) { c.CharacterInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, c.Name); }
|
||||
}
|
||||
List<CharacterInfo> characterInfos = clients.Select(c => c.CharacterInfo).ToList();
|
||||
|
||||
var botsToSpawn = GetBotsToRespawn();
|
||||
characterInfos.AddRange(botsToSpawn);
|
||||
//bots don't respawn in the campaign
|
||||
if (campaign == null)
|
||||
{
|
||||
var botsToSpawn = GetBotsToRespawn();
|
||||
characterInfos.AddRange(botsToSpawn);
|
||||
}
|
||||
|
||||
GameMain.Server.AssignJobs(clients);
|
||||
foreach (Client c in clients)
|
||||
@@ -272,11 +276,10 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
bool bot = i >= clients.Count;
|
||||
|
||||
characterInfos[i].CurrentOrder = null;
|
||||
characterInfos[i].CurrentOrderOption = null;
|
||||
characterInfos[i].ClearCurrentOrders();
|
||||
|
||||
var character = Character.Create(characterInfos[i], shuttleSpawnPoints[i].WorldPosition, characterInfos[i].Name, isRemotePlayer: !bot, hasAi: bot);
|
||||
character.TeamID = Character.TeamType.Team1;
|
||||
character.TeamID = CharacterTeamType.Team1;
|
||||
|
||||
if (bot)
|
||||
{
|
||||
@@ -348,9 +351,9 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
//add the ID card tags they should've gotten when spawning in the shuttle
|
||||
foreach (Item item in character.Inventory.Items)
|
||||
foreach (Item item in character.Inventory.AllItems.Distinct())
|
||||
{
|
||||
if (item == null || item.Prefab.Identifier != "idcard") { continue; }
|
||||
if (item.Prefab.Identifier != "idcard") { continue; }
|
||||
foreach (string s in shuttleSpawnPoints[i].IdCardTags)
|
||||
{
|
||||
item.AddTag(s);
|
||||
|
||||
@@ -42,6 +42,14 @@ namespace Barotrauma
|
||||
#endif
|
||||
Console.WriteLine("Barotrauma Dedicated Server " + GameMain.Version +
|
||||
" (" + AssemblyInfo.BuildString + ", branch " + AssemblyInfo.GitBranch + ", revision " + AssemblyInfo.GitRevision + ")");
|
||||
if(Console.IsOutputRedirected)
|
||||
{
|
||||
Console.WriteLine("Output redirection detected; colored text and command input will be disabled.");
|
||||
}
|
||||
if(Console.IsInputRedirected)
|
||||
{
|
||||
Console.WriteLine("Redirected input is detected but is not supported by this application. Input will be ignored.");
|
||||
}
|
||||
|
||||
string executableDir = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);
|
||||
Directory.SetCurrentDirectory(executableDir);
|
||||
@@ -123,9 +131,12 @@ namespace Barotrauma
|
||||
sb.AppendLine("\n");
|
||||
sb.AppendLine("Exception: " + exception.Message + " (" + exception.GetType().ToString() + ")");
|
||||
sb.AppendLine("Target site: " +exception.TargetSite.ToString());
|
||||
sb.AppendLine("Stack trace: ");
|
||||
sb.AppendLine(exception.StackTrace.CleanupStackTrace());
|
||||
sb.AppendLine("\n");
|
||||
if (exception.StackTrace != null)
|
||||
{
|
||||
sb.AppendLine("Stack trace: ");
|
||||
sb.AppendLine(exception.StackTrace.CleanupStackTrace());
|
||||
sb.AppendLine("\n");
|
||||
}
|
||||
|
||||
if (exception.InnerException != null)
|
||||
{
|
||||
@@ -134,8 +145,11 @@ namespace Barotrauma
|
||||
{
|
||||
sb.AppendLine("Target site: " + exception.InnerException.TargetSite.ToString());
|
||||
}
|
||||
sb.AppendLine("Stack trace: ");
|
||||
sb.AppendLine(exception.InnerException.StackTrace.CleanupStackTrace());
|
||||
if (exception.InnerException.StackTrace != null)
|
||||
{
|
||||
sb.AppendLine("Stack trace: ");
|
||||
sb.AppendLine(exception.InnerException.StackTrace.CleanupStackTrace());
|
||||
}
|
||||
}
|
||||
|
||||
sb.AppendLine("Last debug messages:");
|
||||
@@ -146,7 +160,11 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
string crashReport = sb.ToString();
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
|
||||
if (!Console.IsOutputRedirected)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
}
|
||||
Console.Write(crashReport);
|
||||
|
||||
File.WriteAllText(filePath,sb.ToString());
|
||||
|
||||
@@ -180,7 +180,7 @@ namespace Barotrauma
|
||||
if (allowNew && !targetContainer.OwnInventory.IsFull())
|
||||
{
|
||||
existingItems.Clear();
|
||||
foreach (var item in targetContainer.OwnInventory.Items)
|
||||
foreach (var item in targetContainer.OwnInventory.AllItems.Distinct())
|
||||
{
|
||||
existingItems.Add(item);
|
||||
}
|
||||
@@ -205,7 +205,7 @@ namespace Barotrauma
|
||||
base.Update(deltaTime);
|
||||
if (target == null)
|
||||
{
|
||||
target = targetContainer.OwnInventory.Items.FirstOrDefault(item => item != null && item.Prefab.Identifier == (containedPrefab != null ? itemContainerId : identifier) && !existingItems.Contains(item));
|
||||
target = targetContainer.ContainedItems.FirstOrDefault(item => item.Prefab.Identifier == (containedPrefab != null ? itemContainerId : identifier) && !existingItems.Contains(item));
|
||||
if (target != null)
|
||||
{
|
||||
if (containedPrefab != null)
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Barotrauma
|
||||
if (sabotageContainerIds.Contains(item.prefab.Identifier))
|
||||
{
|
||||
++totalAmount;
|
||||
if (item.OwnInventory.Items.Length <= 0 || item.OwnInventory.Items.All(containedItem => containedItem != null && !validReplacementIds.Contains(containedItem.Prefab.Identifier)))
|
||||
if (item.OwnInventory.AllItems.All(containedItem => !validReplacementIds.Contains(containedItem.Prefab.Identifier)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -19,10 +19,10 @@ namespace Barotrauma
|
||||
// All traitor related functionality should use the following interface for generating random values
|
||||
public static double RandomDouble() => Random.NextDouble();
|
||||
|
||||
public readonly Dictionary<Character.TeamType, Traitor.TraitorMission> Missions = new Dictionary<Character.TeamType, Traitor.TraitorMission>();
|
||||
public readonly Dictionary<CharacterTeamType, Traitor.TraitorMission> Missions = new Dictionary<CharacterTeamType, Traitor.TraitorMission>();
|
||||
|
||||
public string GetCodeWords(Character.TeamType team) => Missions.TryGetValue(team, out var mission) ? mission.CodeWords : "";
|
||||
public string GetCodeResponse(Character.TeamType team) => Missions.TryGetValue(team, out var mission) ? mission.CodeResponse : "";
|
||||
public string GetCodeWords(CharacterTeamType team) => Missions.TryGetValue(team, out var mission) ? mission.CodeWords : "";
|
||||
public string GetCodeResponse(CharacterTeamType team) => Missions.TryGetValue(team, out var mission) ? mission.CodeResponse : "";
|
||||
|
||||
public IEnumerable<Traitor> Traitors => Missions.Values.SelectMany(mission => mission.Traitors.Values);
|
||||
|
||||
@@ -87,18 +87,18 @@ namespace Barotrauma
|
||||
{
|
||||
bool missionCompleted = false;
|
||||
bool gameShouldEnd = false;
|
||||
Character.TeamType winningTeam = Character.TeamType.None;
|
||||
CharacterTeamType winningTeam = CharacterTeamType.None;
|
||||
foreach (var mission in Missions)
|
||||
{
|
||||
mission.Value.Update(deltaTime, () =>
|
||||
{
|
||||
switch (mission.Key)
|
||||
{
|
||||
case Character.TeamType.Team1:
|
||||
winningTeam = (winningTeam == Character.TeamType.None) ? Character.TeamType.Team2 : Character.TeamType.None;
|
||||
case CharacterTeamType.Team1:
|
||||
winningTeam = (winningTeam == CharacterTeamType.None) ? CharacterTeamType.Team2 : CharacterTeamType.None;
|
||||
break;
|
||||
case Character.TeamType.Team2:
|
||||
winningTeam = (winningTeam == Character.TeamType.None) ? Character.TeamType.Team1 : Character.TeamType.None;
|
||||
case CharacterTeamType.Team2:
|
||||
winningTeam = (winningTeam == CharacterTeamType.None) ? CharacterTeamType.Team1 : CharacterTeamType.None;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -137,13 +137,13 @@ namespace Barotrauma
|
||||
startCountdown = MathHelper.Lerp(server.ServerSettings.TraitorsMinRestartDelay, server.ServerSettings.TraitorsMaxRestartDelay, (float)RandomDouble());
|
||||
return;
|
||||
}
|
||||
if (Character.CharacterList.Count(c => !c.IsDead && c.TeamID == Character.TeamType.Team1 || c.TeamID == Character.TeamType.Team2) <= 1)
|
||||
if (Character.CharacterList.Count(c => !c.IsDead && c.TeamID == CharacterTeamType.Team1 || c.TeamID == CharacterTeamType.Team2) <= 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (GameMain.GameSession.Mission is CombatMission)
|
||||
if (GameMain.GameSession.Missions.Any(m => m is CombatMission))
|
||||
{
|
||||
var teamIds = new[] { Character.TeamType.Team1, Character.TeamType.Team2 };
|
||||
var teamIds = new[] { CharacterTeamType.Team1, CharacterTeamType.Team2 };
|
||||
foreach (var teamId in teamIds)
|
||||
{
|
||||
if (server.ConnectedClients.Count(c => c.Character != null && !c.Character.IsDead && c.TeamID == teamId) < 2)
|
||||
@@ -170,11 +170,11 @@ namespace Barotrauma
|
||||
{
|
||||
var mission = TraitorMissionPrefab.RandomPrefab()?.Instantiate();
|
||||
if (mission != null) {
|
||||
if (mission.CanBeStarted(server, this, Character.TeamType.None))
|
||||
if (mission.CanBeStarted(server, this, CharacterTeamType.None))
|
||||
{
|
||||
if (mission.Start(server, this, Character.TeamType.None))
|
||||
if (mission.Start(server, this, CharacterTeamType.None))
|
||||
{
|
||||
Missions.Add(Character.TeamType.None, mission);
|
||||
Missions.Add(CharacterTeamType.None, mission);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,13 +87,13 @@ namespace Barotrauma
|
||||
return pendingObjectives.Find(objective => objective.Roles.Contains(traitor.Role));
|
||||
}
|
||||
|
||||
protected List<Tuple<Client, Character>> FindTraitorCandidates(GameServer server, Character.TeamType team, RoleFilter traitorRoleFilter)
|
||||
protected List<Tuple<Client, Character>> FindTraitorCandidates(GameServer server, CharacterTeamType team, RoleFilter traitorRoleFilter)
|
||||
{
|
||||
var traitorCandidates = new List<Tuple<Client, Character>>();
|
||||
foreach (Client c in server.ConnectedClients)
|
||||
{
|
||||
if (c.Character == null || c.Character.IsDead || c.Character.Removed || !traitorRoleFilter(c.Character) ||
|
||||
(team != Character.TeamType.None && c.Character.TeamID != team))
|
||||
(team != CharacterTeamType.None && c.Character.TeamID != team))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -115,7 +115,7 @@ namespace Barotrauma
|
||||
return characters;
|
||||
}
|
||||
|
||||
protected List<Tuple<string, Tuple<Client, Character>>> AssignTraitors(GameServer server, TraitorManager traitorManager, Character.TeamType team)
|
||||
protected List<Tuple<string, Tuple<Client, Character>>> AssignTraitors(GameServer server, TraitorManager traitorManager, CharacterTeamType team)
|
||||
{
|
||||
List<Character> characters = FindCharacters();
|
||||
#if !ALLOW_SOLO_TRAITOR
|
||||
@@ -176,7 +176,7 @@ namespace Barotrauma
|
||||
return assignedCandidates;
|
||||
}
|
||||
|
||||
public bool CanBeStarted(GameServer server, TraitorManager traitorManager, Character.TeamType team)
|
||||
public bool CanBeStarted(GameServer server, TraitorManager traitorManager, CharacterTeamType team)
|
||||
{
|
||||
foreach (var role in Roles)
|
||||
{
|
||||
@@ -189,7 +189,7 @@ namespace Barotrauma
|
||||
return AssignTraitors(server, traitorManager, team) != null;
|
||||
}
|
||||
|
||||
public bool Start(GameServer server, TraitorManager traitorManager, Character.TeamType team)
|
||||
public bool Start(GameServer server, TraitorManager traitorManager, CharacterTeamType team)
|
||||
{
|
||||
var assignedCandidates = AssignTraitors(server, traitorManager, team);
|
||||
if (assignedCandidates == null)
|
||||
@@ -249,7 +249,7 @@ namespace Barotrauma
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (Traitors.Values.Any(traitor => traitor.Character?.IsDead ?? true || traitor.Character.Removed))
|
||||
if (Traitors.Values.Any(traitor => traitor.Character == null || traitor.Character.IsDead || traitor.Character.Removed))
|
||||
{
|
||||
Traitors.Values.ForEach(traitor => traitor.UpdateCurrentObjective("", Identifier));
|
||||
pendingObjectives.Clear();
|
||||
|
||||
Reference in New Issue
Block a user