Build 0.21.6.0 (1.0 pre-patch)
This commit is contained in:
@@ -14,6 +14,13 @@ namespace Barotrauma
|
||||
/// </summary>
|
||||
public bool Discarded;
|
||||
|
||||
public void ApplyDeathEffects()
|
||||
{
|
||||
RespawnManager.ReduceCharacterSkills(this);
|
||||
RemoveSavedStatValuesOnDeath();
|
||||
CauseOfDeath = null;
|
||||
}
|
||||
|
||||
partial void OnSkillChanged(Identifier skillIdentifier, float prevLevel, float newLevel)
|
||||
{
|
||||
if (Character == null || Character.Removed) { return; }
|
||||
|
||||
@@ -8,8 +8,9 @@ namespace Barotrauma
|
||||
{
|
||||
partial class Character
|
||||
{
|
||||
public Address OwnerClientAddress;
|
||||
public string OwnerClientName;
|
||||
private Address ownerClientAddress;
|
||||
private Option<AccountId> ownerClientAccountId;
|
||||
|
||||
public bool ClientDisconnected;
|
||||
public float KillDisconnectedTimer;
|
||||
|
||||
@@ -19,6 +20,35 @@ namespace Barotrauma
|
||||
|
||||
public bool HealthUpdatePending;
|
||||
|
||||
public void SetOwnerClient(Client client)
|
||||
{
|
||||
if (client == null)
|
||||
{
|
||||
ownerClientAddress = null;
|
||||
ownerClientAccountId = Option<AccountId>.None();
|
||||
IsRemotePlayer = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ownerClientAddress = client.Connection.Endpoint.Address;
|
||||
ownerClientAccountId = client.AccountId;
|
||||
IsRemotePlayer = true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsClientOwner(Client client)
|
||||
{
|
||||
if (ownerClientAccountId.TryUnwrap(out var accountId)
|
||||
&& client.AccountId.TryUnwrap(out var clientId))
|
||||
{
|
||||
return accountId == clientId;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ownerClientAddress == client.Connection.Endpoint.Address;
|
||||
}
|
||||
}
|
||||
|
||||
public float GetPositionUpdateInterval(Client recipient)
|
||||
{
|
||||
if (!Enabled) { return 1000.0f; }
|
||||
@@ -302,12 +332,8 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public void ServerWritePosition(IWriteMessage msg, Client c)
|
||||
public void ServerWritePosition(ReadWriteMessage tempBuffer, Client c)
|
||||
{
|
||||
msg.WriteUInt16(ID);
|
||||
|
||||
IWriteMessage tempBuffer = new WriteOnlyMessage();
|
||||
|
||||
if (this == c.Character)
|
||||
{
|
||||
tempBuffer.WriteBoolean(true);
|
||||
@@ -405,11 +431,6 @@ namespace Barotrauma
|
||||
AIController?.ServerWrite(tempBuffer);
|
||||
HealthUpdatePending = false;
|
||||
}
|
||||
|
||||
tempBuffer.WritePadBits();
|
||||
|
||||
msg.WriteVariableUInt32((uint)tempBuffer.LengthBytes);
|
||||
msg.WriteBytes(tempBuffer.Buffer, 0, tempBuffer.LengthBytes);
|
||||
}
|
||||
|
||||
public virtual void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null)
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Barotrauma.Networking;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
internal static class HealingCooldown
|
||||
{
|
||||
private static readonly Dictionary<Client, DateTimeOffset> HealingCooldowns = new();
|
||||
|
||||
// Little bit less than client's 0.5 second cooldown to account for latency
|
||||
private const float CooldownDuration = 0.4f;
|
||||
|
||||
public static bool IsOnCooldown(Client client)
|
||||
{
|
||||
RemoveExpiredCooldowns();
|
||||
return HealingCooldowns.ContainsKey(client);
|
||||
}
|
||||
|
||||
public static void SetCooldown(Client client)
|
||||
{
|
||||
RemoveExpiredCooldowns();
|
||||
DateTimeOffset newCooldown = DateTimeOffset.UtcNow.AddSeconds(CooldownDuration);
|
||||
HealingCooldowns[client] = newCooldown;
|
||||
}
|
||||
|
||||
private static void RemoveExpiredCooldowns()
|
||||
{
|
||||
HashSet<Client>? expiredCooldowns = null;
|
||||
|
||||
DateTimeOffset now = DateTimeOffset.UtcNow;
|
||||
|
||||
foreach (var (client, cooldown) in HealingCooldowns)
|
||||
{
|
||||
if (now < cooldown) { continue; }
|
||||
|
||||
expiredCooldowns ??= new HashSet<Client>();
|
||||
expiredCooldowns.Add(client);
|
||||
}
|
||||
|
||||
if (expiredCooldowns is null) { return; }
|
||||
|
||||
foreach (Client expiredCooldown in expiredCooldowns)
|
||||
{
|
||||
HealingCooldowns.Remove(expiredCooldown);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1374,7 +1374,7 @@ namespace Barotrauma
|
||||
MultiPlayerCampaign.StartCampaignSetup();
|
||||
return;
|
||||
}
|
||||
if (!GameMain.Server.StartGame()) { NewMessage("Failed to start a new round", Color.Yellow); }
|
||||
if (!GameMain.Server.TryStartGame()) { NewMessage("Failed to start a new round", Color.Yellow); }
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
@@ -66,6 +66,7 @@ namespace Barotrauma
|
||||
|
||||
public static ContentPackage VanillaContent => ContentPackageManager.VanillaCorePackage;
|
||||
|
||||
|
||||
public readonly string[] CommandLineArgs;
|
||||
|
||||
public GameMain(string[] args)
|
||||
|
||||
@@ -27,12 +27,9 @@ namespace Barotrauma
|
||||
AnyOneAllowedToManageCampaign(permissions);
|
||||
}
|
||||
|
||||
public bool AllowedToManageWallets(Client client)
|
||||
public static bool AllowedToManageWallets(Client client)
|
||||
{
|
||||
return
|
||||
client.HasPermission(ClientPermissions.ManageCampaign) ||
|
||||
client.HasPermission(ClientPermissions.ManageMoney) ||
|
||||
IsOwner(client);
|
||||
return AllowedToManageCampaign(client, ClientPermissions.ManageMoney);
|
||||
}
|
||||
|
||||
public override void ShowStartMessage()
|
||||
|
||||
+9
-2
@@ -109,15 +109,22 @@ namespace Barotrauma
|
||||
return AccountId == other.AccountId && other.ClientAddress == ClientAddress;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
itemData = null;
|
||||
healthData = null;
|
||||
WalletData = null;
|
||||
}
|
||||
|
||||
public void SpawnInventoryItems(Character character, Inventory inventory)
|
||||
{
|
||||
if (character == null)
|
||||
{
|
||||
throw new System.InvalidOperationException($"Failed to spawn inventory items. Character was null.");
|
||||
throw new InvalidOperationException($"Failed to spawn inventory items. Character was null.");
|
||||
}
|
||||
if (itemData == null)
|
||||
{
|
||||
throw new System.InvalidOperationException($"Failed to spawn inventory items for the character \"{character.Name}\". No saved inventory data.");
|
||||
throw new InvalidOperationException($"Failed to spawn inventory items for the character \"{character.Name}\". No saved inventory data.");
|
||||
}
|
||||
character.SpawnInventoryItems(inventory, itemData.FromPackage(null));
|
||||
}
|
||||
|
||||
+13
-7
@@ -146,7 +146,7 @@ namespace Barotrauma
|
||||
{
|
||||
NextLevel = map.SelectedConnection?.LevelData ?? map.CurrentLocation.LevelData;
|
||||
MirrorLevel = false;
|
||||
GameMain.Server.StartGame();
|
||||
GameMain.Server.TryStartGame();
|
||||
}
|
||||
|
||||
public static void StartCampaignSetup()
|
||||
@@ -240,9 +240,7 @@ namespace Barotrauma
|
||||
//reduce skills if the character has died
|
||||
if (characterInfo.CauseOfDeath != null && characterInfo.CauseOfDeath.Type != CauseOfDeathType.Disconnected)
|
||||
{
|
||||
RespawnManager.ReduceCharacterSkills(characterInfo);
|
||||
characterInfo.RemoveSavedStatValuesOnDeath();
|
||||
characterInfo.CauseOfDeath = null;
|
||||
characterInfo.ApplyDeathEffects();
|
||||
}
|
||||
c.CharacterInfo = characterInfo;
|
||||
SetClientCharacterData(c);
|
||||
@@ -254,13 +252,21 @@ namespace Barotrauma
|
||||
{
|
||||
if (data.HasSpawned && !GameMain.Server.ConnectedClients.Any(c => data.MatchesClient(c)))
|
||||
{
|
||||
var character = Character.CharacterList.Find(c => c.Info == data.CharacterInfo && !c.IsHusk);
|
||||
if (character != null && (!character.IsDead || character.CauseOfDeath?.Type == CauseOfDeathType.Disconnected))
|
||||
var character = Character.CharacterList.Find(c => c.Info == data.CharacterInfo && !c.IsHusk);
|
||||
if (character != null &&
|
||||
(!character.IsDead || character.CauseOfDeath?.Type == CauseOfDeathType.Disconnected))
|
||||
{
|
||||
//character still alive (or killed by Disconnect) -> save it as-is
|
||||
characterData.RemoveAll(cd => cd.IsDuplicate(data));
|
||||
data.Refresh(character);
|
||||
characterData.Add(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
//character dead or removed -> reduce skills, remove items, health data, etc
|
||||
data.CharacterInfo.ApplyDeathEffects();
|
||||
data.Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -395,7 +401,7 @@ namespace Barotrauma
|
||||
yield return new WaitForSeconds(EndTransitionDuration * 0.5f);
|
||||
}
|
||||
|
||||
GameMain.Server.StartGame();
|
||||
GameMain.Server.TryStartGame();
|
||||
|
||||
yield return CoroutineStatus.Success;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Barotrauma.Items.Components;
|
||||
using Barotrauma.Extensions;
|
||||
using Barotrauma.Items.Components;
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System.Collections.Generic;
|
||||
@@ -19,7 +20,7 @@ namespace Barotrauma
|
||||
bool accessible = c.Character.CanAccessInventory(this);
|
||||
if (this is CharacterInventory characterInventory && accessible)
|
||||
{
|
||||
if (Owner == null || !(Owner is Character ownerCharacter))
|
||||
if (Owner == null || Owner is not Character ownerCharacter)
|
||||
{
|
||||
accessible = false;
|
||||
}
|
||||
@@ -39,7 +40,7 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (ushort id in newItemIDs[i])
|
||||
{
|
||||
if (!(Entity.FindEntityByID(id) is Item item)) { continue; }
|
||||
if (Entity.FindEntityByID(id) is not Item item) { continue; }
|
||||
item.PositionUpdateInterval = 0.0f;
|
||||
if (item.ParentInventory != null && item.ParentInventory != this)
|
||||
{
|
||||
@@ -94,7 +95,15 @@ namespace Barotrauma
|
||||
{
|
||||
foreach (ushort id in newItemIDs[i])
|
||||
{
|
||||
if (!(Entity.FindEntityByID(id) is Item item) || slots[i].Contains(item)) { continue; }
|
||||
if (Entity.FindEntityByID(id) is not Item item || slots[i].Contains(item)) { continue; }
|
||||
|
||||
if (item.GetComponent<Pickable>() is not Pickable pickable ||
|
||||
(pickable.IsAttached && !pickable.PickingDone) ||
|
||||
item.AllowedSlots.None())
|
||||
{
|
||||
DebugConsole.AddWarning($"Client {c.Name} tried to pick up a non-pickable item \"{item}\" (parent inventory: {item.ParentInventory?.Owner.ToString() ?? "null"})");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
@@ -105,7 +114,7 @@ namespace Barotrauma
|
||||
(c.Character == null || item.PreviousParentInventory == null || !c.Character.CanAccessInventory(item.PreviousParentInventory)))
|
||||
{
|
||||
#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);
|
||||
DebugConsole.NewMessage($"Client {c.Name} failed to pick up item \"{item}\" (parent inventory: {item.ParentInventory?.Owner.ToString() ?? "null"}). No access.", Color.Yellow);
|
||||
#endif
|
||||
if (item.body != null && !c.PendingPositionUpdates.Contains(item))
|
||||
{
|
||||
|
||||
@@ -153,25 +153,27 @@ namespace Barotrauma
|
||||
(components[containerIndex] as ItemContainer).Inventory.ServerEventRead(msg, c);
|
||||
break;
|
||||
case EventType.Treatment:
|
||||
if (c.Character == null || !c.Character.CanInteractWith(this)) return;
|
||||
if (c.Character == null || !c.Character.CanInteractWith(this)) { return; }
|
||||
|
||||
UInt16 characterID = msg.ReadUInt16();
|
||||
byte limbIndex = msg.ReadByte();
|
||||
|
||||
Character targetCharacter = FindEntityByID(characterID) as Character;
|
||||
if (targetCharacter == null) break;
|
||||
if (targetCharacter != c.Character && c.Character.SelectedCharacter != targetCharacter) break;
|
||||
if (HealingCooldown.IsOnCooldown(c)) { return; }
|
||||
if (FindEntityByID(characterID) is not Character targetCharacter) { break; }
|
||||
if (targetCharacter != c.Character && c.Character.SelectedCharacter != targetCharacter) { break; }
|
||||
|
||||
HealingCooldown.SetCooldown(c);
|
||||
|
||||
Limb targetLimb = limbIndex < targetCharacter.AnimController.Limbs.Length ? targetCharacter.AnimController.Limbs[limbIndex] : null;
|
||||
|
||||
if (ContainedItems == null || ContainedItems.All(i => i == null))
|
||||
if (ContainedItems == null || ContainedItems.All(static i => i == null))
|
||||
{
|
||||
GameServer.Log(GameServer.CharacterLogName(c.Character) + " used item " + Name, ServerLog.MessageType.ItemInteraction);
|
||||
GameServer.Log($"{GameServer.CharacterLogName(c.Character)} used item {Name}", ServerLog.MessageType.ItemInteraction);
|
||||
}
|
||||
else
|
||||
{
|
||||
GameServer.Log(
|
||||
GameServer.CharacterLogName(c.Character) + " used item " + Name + " (contained items: " + string.Join(", ", ContainedItems.Select(i => i.Name)) + ")",
|
||||
$"{GameServer.CharacterLogName(c.Character)} used item {Name} (contained items: {string.Join(", ", ContainedItems.Select(i => i.Name))})",
|
||||
ServerLog.MessageType.ItemInteraction);
|
||||
}
|
||||
|
||||
@@ -348,15 +350,9 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public void ServerWritePosition(IWriteMessage msg, Client c)
|
||||
public void ServerWritePosition(ReadWriteMessage tempBuffer, Client c)
|
||||
{
|
||||
msg.WriteUInt16(ID);
|
||||
|
||||
IWriteMessage tempBuffer = new WriteOnlyMessage();
|
||||
body.ServerWrite(tempBuffer);
|
||||
msg.WriteVariableUInt32((uint)tempBuffer.LengthBytes);
|
||||
msg.WriteBytes(tempBuffer.Buffer, 0, tempBuffer.LengthBytes);
|
||||
msg.WritePadBits();
|
||||
}
|
||||
|
||||
public void CreateServerEvent<T>(T ic) where T : ItemComponent, IServerSerializable
|
||||
@@ -378,7 +374,7 @@ namespace Barotrauma
|
||||
if (!components.Contains(ic)) { return; }
|
||||
|
||||
var eventData = new ComponentStateEventData(ic, extraData);
|
||||
if (!ic.ValidateEventData(eventData)) { throw new Exception($"Component event creation failed: {typeof(T).Name}.{nameof(ItemComponent.ValidateEventData)} returned false"); }
|
||||
if (!ic.ValidateEventData(eventData)) { throw new Exception($"Component event creation for the item \"{Prefab.Identifier}\" failed: {typeof(T).Name}.{nameof(ItemComponent.ValidateEventData)} returned false."); }
|
||||
GameMain.Server.CreateEntityEvent(this, eventData);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,14 +5,9 @@ namespace Barotrauma
|
||||
{
|
||||
partial class Submarine
|
||||
{
|
||||
public void ServerWritePosition(IWriteMessage msg, Client c)
|
||||
public void ServerWritePosition(ReadWriteMessage tempBuffer, Client c)
|
||||
{
|
||||
msg.WriteUInt16(ID);
|
||||
IWriteMessage tempBuffer = new WriteOnlyMessage();
|
||||
subBody.Body.ServerWrite(tempBuffer);
|
||||
msg.WriteByte((byte)tempBuffer.LengthBytes);
|
||||
msg.WriteBytes(tempBuffer.Buffer, 0, tempBuffer.LengthBytes);
|
||||
msg.WritePadBits();
|
||||
}
|
||||
|
||||
public void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null)
|
||||
|
||||
@@ -11,10 +11,10 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
private static UInt32 LastIdentifier = 0;
|
||||
|
||||
public bool Expired => ExpirationTime is { } expirationTime && DateTime.Now > expirationTime;
|
||||
public bool Expired => ExpirationTime.TryUnwrap(out var expirationTime) && SerializableDateTime.LocalNow > expirationTime;
|
||||
|
||||
public BannedPlayer(
|
||||
string name, Either<Address, AccountId> addressOrAccountId, string reason, DateTime? expirationTime)
|
||||
string name, Either<Address, AccountId> addressOrAccountId, string reason, Option<SerializableDateTime> expirationTime)
|
||||
{
|
||||
this.Name = name;
|
||||
this.AddressOrAccountId = addressOrAccountId;
|
||||
@@ -39,6 +39,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
LoadBanList();
|
||||
}
|
||||
RemoveExpired();
|
||||
}
|
||||
|
||||
private void LoadLegacyBanList()
|
||||
@@ -69,7 +70,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (DateTime.TryParse(separatedLine[2], out DateTime parsedTime))
|
||||
{
|
||||
expirationTime = parsedTime;
|
||||
expirationTime = DateTime.SpecifyKind(parsedTime, DateTimeKind.Local);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -80,15 +81,18 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
string reason = separatedLine.Length > 3 ? string.Join(",", separatedLine.Skip(3)) : "";
|
||||
|
||||
if (expirationTime.HasValue && DateTime.Now > expirationTime.Value) { continue; }
|
||||
var serializableExpirationTime
|
||||
= expirationTime.HasValue
|
||||
? Option<SerializableDateTime>.Some(new SerializableDateTime(expirationTime.Value))
|
||||
: Option<SerializableDateTime>.None();
|
||||
|
||||
if (AccountId.Parse(endpointStr).TryUnwrap(out var accountId))
|
||||
{
|
||||
bannedPlayers.Add(new BannedPlayer(name, accountId, reason, expirationTime));
|
||||
bannedPlayers.Add(new BannedPlayer(name, accountId, reason, serializableExpirationTime));
|
||||
}
|
||||
else if (Address.Parse(endpointStr).TryUnwrap(out var address))
|
||||
{
|
||||
bannedPlayers.Add(new BannedPlayer(name, address, reason, expirationTime));
|
||||
bannedPlayers.Add(new BannedPlayer(name, address, reason, serializableExpirationTime));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,10 +113,22 @@ namespace Barotrauma.Networking
|
||||
|
||||
var name = element.GetAttributeString("name", "")!;
|
||||
var reason = element.GetAttributeString("reason", "")!;
|
||||
DateTime? expirationTime = DateTime.FromBinary(unchecked((long)element.GetAttributeUInt64("expirationtime", 0)));
|
||||
|
||||
if (expirationTime < DateTime.Now) { expirationTime = null; }
|
||||
|
||||
var expirationTime = Option<SerializableDateTime>.None();
|
||||
var expirationTimeStr = element.GetAttributeString("expirationtime", "")!;
|
||||
|
||||
if (UInt64.TryParse(expirationTimeStr, out var binaryDateTime) && binaryDateTime > 0)
|
||||
{
|
||||
// Backwards compatibility: if expirationtime is stored as an int,
|
||||
// convert to SerializableDateTime with local timezone because
|
||||
// banlists used to assume local time
|
||||
expirationTime = Option<SerializableDateTime>.Some(
|
||||
new SerializableDateTime(
|
||||
DateTime.FromBinary((long)binaryDateTime),
|
||||
SerializableTimeZone.LocalTimeZone));
|
||||
}
|
||||
|
||||
expirationTime = expirationTime.Fallback(SerializableDateTime.Parse(expirationTimeStr));
|
||||
|
||||
if (accountId.IsNone() && address.IsNone()) { return Option<BannedPlayer>.None(); }
|
||||
|
||||
Either<Address, AccountId> addressOrAccountId = accountId.TryUnwrap(out var accId)
|
||||
@@ -171,14 +187,14 @@ namespace Barotrauma.Networking
|
||||
|
||||
string logMsg = "Banned " + name;
|
||||
if (!string.IsNullOrEmpty(reason)) { logMsg += ", reason: " + reason; }
|
||||
if (duration.HasValue) { logMsg += ", duration: " + duration.Value.ToString(); }
|
||||
if (duration.HasValue) { logMsg += ", duration: " + duration.Value; }
|
||||
|
||||
DebugConsole.Log(logMsg);
|
||||
|
||||
DateTime? expirationTime = null;
|
||||
Option<SerializableDateTime> expirationTime = Option<SerializableDateTime>.None();
|
||||
if (duration.HasValue)
|
||||
{
|
||||
expirationTime = DateTime.Now + duration.Value;
|
||||
expirationTime = Option<SerializableDateTime>.Some(new SerializableDateTime(DateTime.Now + duration.Value));
|
||||
}
|
||||
|
||||
bannedPlayers.Add(new BannedPlayer(name, addressOrAccountId, reason, expirationTime));
|
||||
@@ -232,9 +248,10 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
retVal.SetAttributeValue("address", address.StringRepresentation);
|
||||
}
|
||||
if (bannedPlayer.ExpirationTime is { } expirationTime)
|
||||
if (bannedPlayer.ExpirationTime.TryUnwrap(out var expirationTime))
|
||||
{
|
||||
retVal.SetAttributeValue("expirationtime", unchecked((ulong)expirationTime.ToBinary()));
|
||||
#warning TODO: stop writing binary DateTime representation after this gets on main
|
||||
retVal.SetAttributeValue("expirationtime", expirationTime.ToLocalValue().ToBinary());
|
||||
}
|
||||
|
||||
return retVal;
|
||||
@@ -269,11 +286,11 @@ namespace Barotrauma.Networking
|
||||
|
||||
outMsg.WriteString(bannedPlayer.Name);
|
||||
outMsg.WriteUInt32(bannedPlayer.UniqueIdentifier);
|
||||
outMsg.WriteBoolean(bannedPlayer.ExpirationTime != null);
|
||||
outMsg.WriteBoolean(bannedPlayer.ExpirationTime.IsSome());
|
||||
outMsg.WritePadBits();
|
||||
if (bannedPlayer.ExpirationTime != null)
|
||||
if (bannedPlayer.ExpirationTime.TryUnwrap(out var expirationTime))
|
||||
{
|
||||
double hoursFromNow = (bannedPlayer.ExpirationTime.Value - DateTime.Now).TotalHours;
|
||||
double hoursFromNow = (expirationTime.ToUtcValue() - DateTime.UtcNow).TotalHours;
|
||||
outMsg.WriteDouble(hoursFromNow);
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
private DateTime roundStartTime;
|
||||
|
||||
private bool wasReadyToStartAutomatically;
|
||||
private bool autoRestartTimerRunning;
|
||||
private float endRoundTimer;
|
||||
|
||||
@@ -139,6 +140,7 @@ namespace Barotrauma.Networking
|
||||
ServerSettings = new ServerSettings(this, name, port, queryPort, maxPlayers, isPublic, attemptUPnP);
|
||||
KarmaManager.SelectPreset(ServerSettings.KarmaPreset);
|
||||
ServerSettings.SetPassword(password);
|
||||
ServerSettings.SaveSettings();
|
||||
|
||||
Voting = new Voting();
|
||||
|
||||
@@ -366,8 +368,7 @@ namespace Barotrauma.Networking
|
||||
character.KillDisconnectedTimer += deltaTime;
|
||||
character.SetStun(1.0f);
|
||||
|
||||
Client owner = connectedClients.Find(c => (c.Character == null || c.Character == character) && c.AddressMatches(character.OwnerClientAddress));
|
||||
|
||||
Client owner = connectedClients.Find(c => (c.Character == null || c.Character == character) && character.IsClientOwner(c));
|
||||
if ((OwnerConnection == null || owner?.Connection != OwnerConnection) && character.KillDisconnectedTimer > ServerSettings.KillDisconnectedTime)
|
||||
{
|
||||
character.Kill(CauseOfDeathType.Disconnected, null);
|
||||
@@ -504,8 +505,7 @@ namespace Barotrauma.Networking
|
||||
initiatedStartGame = false;
|
||||
}
|
||||
}
|
||||
else if (Screen.Selected == GameMain.NetLobbyScreen && !GameStarted && !initiatedStartGame &&
|
||||
(GameMain.NetLobbyScreen.SelectedMode != GameModePreset.MultiPlayerCampaign || GameMain.GameSession?.GameMode is MultiPlayerCampaign))
|
||||
else if (Screen.Selected == GameMain.NetLobbyScreen && !GameStarted && !initiatedStartGame)
|
||||
{
|
||||
if (ServerSettings.AutoRestart)
|
||||
{
|
||||
@@ -526,18 +526,25 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
bool readyToStartAutomatically = false;
|
||||
if (ServerSettings.AutoRestart && autoRestartTimerRunning && ServerSettings.AutoRestartTimer < 0.0f)
|
||||
{
|
||||
StartGame();
|
||||
readyToStartAutomatically = true;
|
||||
}
|
||||
else if (ServerSettings.StartWhenClientsReady)
|
||||
{
|
||||
int clientsReady = connectedClients.Count(c => c.GetVote<bool>(VoteType.StartRound));
|
||||
if (clientsReady / (float)connectedClients.Count >= ServerSettings.StartWhenClientsReadyRatio)
|
||||
{
|
||||
StartGame();
|
||||
readyToStartAutomatically = true;
|
||||
}
|
||||
}
|
||||
if (readyToStartAutomatically)
|
||||
{
|
||||
if (!wasReadyToStartAutomatically) { GameMain.NetLobbyScreen.LastUpdateID++; }
|
||||
TryStartGame();
|
||||
}
|
||||
wasReadyToStartAutomatically = readyToStartAutomatically;
|
||||
}
|
||||
|
||||
for (int i = disconnectedClients.Count - 1; i >= 0; i--)
|
||||
@@ -763,7 +770,7 @@ namespace Barotrauma.Networking
|
||||
else
|
||||
{
|
||||
string localSavePath = SaveUtil.CreateSavePath(SaveUtil.SaveType.Multiplayer, saveName);
|
||||
if (connectedClient.HasPermission(ClientPermissions.SelectMode) || connectedClient.HasPermission(ClientPermissions.ManageCampaign))
|
||||
if (CampaignMode.AllowedToManageCampaign(connectedClient, ClientPermissions.ManageRound))
|
||||
{
|
||||
ServerSettings.CampaignSettings = settings;
|
||||
ServerSettings.SaveSettings();
|
||||
@@ -779,7 +786,10 @@ namespace Barotrauma.Networking
|
||||
SendDirectChatMessage(TextManager.Get("CampaignStartFailedRoundRunning").Value, connectedClient, ChatMessageType.MessageBox);
|
||||
return;
|
||||
}
|
||||
if (connectedClient.HasPermission(ClientPermissions.SelectMode) || connectedClient.HasPermission(ClientPermissions.ManageCampaign)) { MultiPlayerCampaign.LoadCampaign(saveName); }
|
||||
if (CampaignMode.AllowedToManageCampaign(connectedClient, ClientPermissions.ManageRound))
|
||||
{
|
||||
MultiPlayerCampaign.LoadCampaign(saveName);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ClientPacketHeader.VOICE:
|
||||
@@ -1389,13 +1399,13 @@ namespace Barotrauma.Networking
|
||||
if (end)
|
||||
{
|
||||
if (mpCampaign == null ||
|
||||
CampaignMode.AllowedToManageCampaign(sender, ClientPermissions.ManageRound) ||
|
||||
CampaignMode.AllowedToManageCampaign(sender, ClientPermissions.ManageCampaign))
|
||||
CampaignMode.AllowedToManageCampaign(sender, ClientPermissions.ManageRound))
|
||||
{
|
||||
bool save = inc.ReadBoolean();
|
||||
bool quitCampaign = inc.ReadBoolean();
|
||||
if (GameStarted)
|
||||
{
|
||||
Log("Client \"" + GameServer.ClientLogName(sender) + "\" ended the round.", ServerLog.MessageType.ServerMessage);
|
||||
Log($"Client \"{ClientLogName(sender)}\" ended the round.", ServerLog.MessageType.ServerMessage);
|
||||
if (mpCampaign != null && Level.IsLoadedFriendlyOutpost && save)
|
||||
{
|
||||
mpCampaign.SavePlayers();
|
||||
@@ -1409,6 +1419,14 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
EndGame(wasSaved: save);
|
||||
}
|
||||
else if (mpCampaign != null)
|
||||
{
|
||||
Log($"Client \"{ClientLogName(sender)}\" quit the currently active campaign.", ServerLog.MessageType.ServerMessage);
|
||||
GameMain.GameSession = null;
|
||||
GameMain.NetLobbyScreen.SelectedModeIdentifier = GameModePreset.Sandbox.Identifier;
|
||||
GameMain.NetLobbyScreen.LastUpdateID++;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1425,12 +1443,11 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
MultiPlayerCampaign.LoadCampaign(GameMain.GameSession.SavePath);
|
||||
}
|
||||
|
||||
}
|
||||
else if (!GameStarted && !initiatedStartGame)
|
||||
{
|
||||
Log("Client \"" + ClientLogName(sender) + "\" started the round.", ServerLog.MessageType.ServerMessage);
|
||||
StartGame();
|
||||
TryStartGame();
|
||||
}
|
||||
else if (mpCampaign != null && (CampaignMode.AllowedToManageCampaign(sender, ClientPermissions.ManageCampaign) || CampaignMode.AllowedToManageCampaign(sender, ClientPermissions.ManageMap)))
|
||||
{
|
||||
@@ -1492,20 +1509,10 @@ namespace Barotrauma.Networking
|
||||
case ClientPermissions.SelectMode:
|
||||
UInt16 modeIndex = inc.ReadUInt16();
|
||||
GameMain.NetLobbyScreen.SelectedModeIndex = modeIndex;
|
||||
Log("Gamemode changed to " + GameMain.NetLobbyScreen.GameModes[GameMain.NetLobbyScreen.SelectedModeIndex].Name.Value, ServerLog.MessageType.ServerMessage);
|
||||
|
||||
if (GameMain.NetLobbyScreen.GameModes[modeIndex].Identifier == "multiplayercampaign")
|
||||
Log("Gamemode changed to " + (GameMain.NetLobbyScreen.SelectedMode?.Name.Value ?? "none"), ServerLog.MessageType.ServerMessage);
|
||||
if (GameMain.NetLobbyScreen.GameModes[modeIndex] == GameModePreset.MultiPlayerCampaign)
|
||||
{
|
||||
const int MaxSaves = 255;
|
||||
var saveInfos = SaveUtil.GetSaveFiles(SaveUtil.SaveType.Multiplayer, includeInCompatible: false);
|
||||
IWriteMessage msg = new WriteOnlyMessage();
|
||||
msg.WriteByte((byte)ServerPacketHeader.CAMPAIGN_SETUP_INFO);
|
||||
msg.WriteByte((byte)Math.Min(saveInfos.Count, MaxSaves));
|
||||
for (int i = 0; i < saveInfos.Count && i < MaxSaves; i++)
|
||||
{
|
||||
msg.WriteNetSerializableStruct(saveInfos[i]);
|
||||
}
|
||||
serverPeer.Send(msg, sender.Connection, DeliveryMethod.Reliable);
|
||||
TrySendCampaignSetupInfo(sender);
|
||||
}
|
||||
break;
|
||||
case ClientPermissions.ManageCampaign:
|
||||
@@ -1612,7 +1619,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
if (GameSettings.CurrentConfig.VerboseLogging)
|
||||
{
|
||||
DebugConsole.NewMessage("Sending initial lobby update", Color.Gray);
|
||||
DebugConsole.NewMessage($"Sending initial lobby update to {c.Name}", Color.Gray);
|
||||
}
|
||||
|
||||
outmsg.WriteByte(c.SessionId);
|
||||
@@ -1745,9 +1752,9 @@ namespace Barotrauma.Networking
|
||||
continue;
|
||||
}
|
||||
|
||||
IWriteMessage tempBuffer = new ReadWriteMessage();
|
||||
tempBuffer.WriteBoolean(entity is Item); tempBuffer.WritePadBits();
|
||||
tempBuffer.WriteUInt32(entity is MapEntity me ? me.Prefab.UintIdentifier : (UInt32)0);
|
||||
var tempBuffer = new ReadWriteMessage();
|
||||
var entityPositionHeader = EntityPositionHeader.FromEntity(entity);
|
||||
tempBuffer.WriteNetSerializableStruct(entityPositionHeader);
|
||||
entityPositionSync.ServerWritePosition(tempBuffer, c);
|
||||
|
||||
//no more room in this packet
|
||||
@@ -1758,6 +1765,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
segmentTable.StartNewSegment(ServerNetSegment.EntityPosition);
|
||||
outmsg.WritePadBits(); //padding is required here to make sure any padding bits within tempBuffer are read correctly
|
||||
outmsg.WriteVariableUInt32((uint)tempBuffer.LengthBytes);
|
||||
outmsg.WriteBytes(tempBuffer.Buffer, 0, tempBuffer.LengthBytes);
|
||||
outmsg.WritePadBits();
|
||||
|
||||
@@ -1934,6 +1942,13 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
outmsg.WriteSingle(autoRestartTimerRunning ? ServerSettings.AutoRestartTimer : 0.0f);
|
||||
}
|
||||
|
||||
if (GameMain.NetLobbyScreen.SelectedMode == GameModePreset.MultiPlayerCampaign &&
|
||||
connectedClients.None(c => c.Connection == OwnerConnection || c.HasPermission(ClientPermissions.ManageRound) || c.HasPermission(ClientPermissions.ManageCampaign)))
|
||||
{
|
||||
//if no-one has permissions to manage the campaign, show the setup UI to everyone
|
||||
TrySendCampaignSetupInfo(c);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1943,9 +1958,8 @@ namespace Barotrauma.Networking
|
||||
settingsBytes = outmsg.LengthBytes - settingsBytes;
|
||||
|
||||
int campaignBytes = outmsg.LengthBytes;
|
||||
var campaign = GameMain.GameSession?.GameMode as MultiPlayerCampaign;
|
||||
if (outmsg.LengthBytes < MsgConstants.MTU - 500 &&
|
||||
campaign != null && campaign.Preset == GameMain.NetLobbyScreen.SelectedMode)
|
||||
GameMain.GameSession?.GameMode is MultiPlayerCampaign campaign && campaign.Preset == GameMain.NetLobbyScreen.SelectedMode)
|
||||
{
|
||||
outmsg.WriteBoolean(true);
|
||||
outmsg.WritePadBits();
|
||||
@@ -2023,7 +2037,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteChatMessages(in SegmentTableWriter<ServerNetSegment> segmentTable, IWriteMessage outmsg, Client c)
|
||||
private static void WriteChatMessages(in SegmentTableWriter<ServerNetSegment> segmentTable, IWriteMessage outmsg, Client c)
|
||||
{
|
||||
c.ChatMsgQueue.RemoveAll(cMsg => !NetIdUtils.IdMoreRecent(cMsg.NetStateID, c.LastRecvChatMsgID));
|
||||
for (int i = 0; i < c.ChatMsgQueue.Count && i < ChatMessage.MaxMessagesPerPacket; i++)
|
||||
@@ -2037,10 +2051,26 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
}
|
||||
|
||||
public bool StartGame()
|
||||
public bool TryStartGame()
|
||||
{
|
||||
if (initiatedStartGame || GameStarted) { return false; }
|
||||
|
||||
GameModePreset selectedMode =
|
||||
Voting.HighestVoted<GameModePreset>(VoteType.Mode, connectedClients) ?? GameMain.NetLobbyScreen.SelectedMode;
|
||||
if (selectedMode == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (selectedMode == GameModePreset.MultiPlayerCampaign && GameMain.GameSession?.GameMode is not MultiPlayerCampaign)
|
||||
{
|
||||
//DebugConsole.ThrowError($"{nameof(TryStartGame)} failed. Cannot start a multiplayer campaign via {nameof(TryStartGame)} - use {nameof(MultiPlayerCampaign.StartNewCampaign)} or {nameof(MultiPlayerCampaign.LoadCampaign)} instead.");
|
||||
if (GameMain.NetLobbyScreen.SelectedMode != GameModePreset.MultiPlayerCampaign)
|
||||
{
|
||||
GameMain.NetLobbyScreen.SelectedModeIdentifier = GameModePreset.MultiPlayerCampaign.Identifier;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Log("Starting a new round...", ServerLog.MessageType.ServerMessage);
|
||||
SubmarineInfo selectedShuttle = GameMain.NetLobbyScreen.SelectedShuttle;
|
||||
|
||||
@@ -2060,23 +2090,13 @@ namespace Barotrauma.Networking
|
||||
return false;
|
||||
}
|
||||
|
||||
GameModePreset selectedMode = Voting.HighestVoted<GameModePreset>(VoteType.Mode, connectedClients);
|
||||
if (selectedMode == null) { selectedMode = GameMain.NetLobbyScreen.SelectedMode; }
|
||||
if (selectedMode == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (selectedMode == GameModePreset.MultiPlayerCampaign && !(GameMain.GameSession?.GameMode is CampaignMode))
|
||||
{
|
||||
DebugConsole.ThrowError("StartGame failed. Cannot start a multiplayer campaign via StartGame - use MultiPlayerCampaign.StartNewCampaign or MultiPlayerCampaign.LoadCampaign instead.");
|
||||
return false;
|
||||
}
|
||||
initiatedStartGame = true;
|
||||
startGameCoroutine = CoroutineManager.StartCoroutine(InitiateStartGame(selectedSub, selectedShuttle, selectedMode), "InitiateStartGame");
|
||||
startGameCoroutine = CoroutineManager.StartCoroutine(InitiateStartGame(selectedSub, selectedShuttle, selectedMode), "InitiateStartGame");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private IEnumerable<CoroutineStatus> InitiateStartGame(SubmarineInfo selectedSub, SubmarineInfo selectedShuttle, GameModePreset selectedMode)
|
||||
{
|
||||
initiatedStartGame = true;
|
||||
@@ -2168,7 +2188,6 @@ namespace Barotrauma.Networking
|
||||
initialSuppliesSpawned = GameMain.GameSession.SubmarineInfo is { InitialSuppliesSpawned: true };
|
||||
}
|
||||
|
||||
|
||||
List<Client> playingClients = new List<Client>(connectedClients);
|
||||
if (ServerSettings.AllowSpectating)
|
||||
{
|
||||
@@ -2413,8 +2432,7 @@ namespace Barotrauma.Networking
|
||||
mpCampaign.ClearSavedExperiencePoints(teamClients[i]);
|
||||
}
|
||||
|
||||
spawnedCharacter.OwnerClientAddress = teamClients[i].Connection.Endpoint.Address;
|
||||
spawnedCharacter.OwnerClientName = teamClients[i].Name;
|
||||
spawnedCharacter.SetOwnerClient(teamClients[i]);
|
||||
}
|
||||
|
||||
for (int i = teamClients.Count; i < teamClients.Count + bots.Count; i++)
|
||||
@@ -2479,7 +2497,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
yield return CoroutineStatus.Running;
|
||||
|
||||
Voting?.ResetVotes(GameMain.Server.ConnectedClients, resetKickVotes: false);
|
||||
Voting.ResetVotes(GameMain.Server.ConnectedClients, resetKickVotes: false);
|
||||
|
||||
GameMain.GameScreen.Select();
|
||||
|
||||
@@ -2507,14 +2525,11 @@ namespace Barotrauma.Networking
|
||||
|
||||
private void SendStartMessage(int seed, string levelSeed, GameSession gameSession, Client client, bool includesFinalize)
|
||||
{
|
||||
MultiPlayerCampaign campaign = GameMain.GameSession?.GameMode as MultiPlayerCampaign;
|
||||
MissionMode missionMode = GameMain.GameSession.GameMode as MissionMode;
|
||||
|
||||
IWriteMessage msg = new WriteOnlyMessage();
|
||||
msg.WriteByte((byte)ServerPacketHeader.STARTGAME);
|
||||
msg.WriteInt32(seed);
|
||||
msg.WriteIdentifier(gameSession.GameMode.Preset.Identifier);
|
||||
bool missionAllowRespawn = missionMode == null || !missionMode.Missions.Any(m => !m.AllowRespawn);
|
||||
bool missionAllowRespawn = GameMain.GameSession.GameMode is not MissionMode missionMode || !missionMode.Missions.Any(m => !m.AllowRespawn);
|
||||
msg.WriteBoolean(ServerSettings.AllowRespawn && missionAllowRespawn);
|
||||
msg.WriteBoolean(ServerSettings.AllowDisguises);
|
||||
msg.WriteBoolean(ServerSettings.AllowRewiring);
|
||||
@@ -2530,7 +2545,7 @@ namespace Barotrauma.Networking
|
||||
|
||||
ServerSettings.WriteMonsterEnabled(msg);
|
||||
|
||||
if (campaign == null)
|
||||
if (GameMain.GameSession?.GameMode is not MultiPlayerCampaign campaign)
|
||||
{
|
||||
msg.WriteString(levelSeed);
|
||||
msg.WriteSingle(ServerSettings.SelectedLevelDifficulty);
|
||||
@@ -2566,6 +2581,23 @@ namespace Barotrauma.Networking
|
||||
serverPeer.Send(msg, client.Connection, DeliveryMethod.Reliable);
|
||||
}
|
||||
|
||||
private bool TrySendCampaignSetupInfo(Client client)
|
||||
{
|
||||
if (!CampaignMode.AllowedToManageCampaign(client, ClientPermissions.ManageRound)) { return false; }
|
||||
|
||||
const int MaxSaves = 255;
|
||||
var saveInfos = SaveUtil.GetSaveFiles(SaveUtil.SaveType.Multiplayer, includeInCompatible: false);
|
||||
IWriteMessage msg = new WriteOnlyMessage();
|
||||
msg.WriteByte((byte)ServerPacketHeader.CAMPAIGN_SETUP_INFO);
|
||||
msg.WriteByte((byte)Math.Min(saveInfos.Count, MaxSaves));
|
||||
for (int i = 0; i < saveInfos.Count && i < MaxSaves; i++)
|
||||
{
|
||||
msg.WriteNetSerializableStruct(saveInfos[i]);
|
||||
}
|
||||
serverPeer.Send(msg, client.Connection, DeliveryMethod.Reliable);
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool IsUsingRespawnShuttle()
|
||||
{
|
||||
return ServerSettings.UseRespawnShuttle || (GameStarted && RespawnManager != null && RespawnManager.UsingShuttle);
|
||||
@@ -3196,16 +3228,16 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
//too far to hear the msg -> don't send
|
||||
if (string.IsNullOrWhiteSpace(modifiedMessage)) continue;
|
||||
if (string.IsNullOrWhiteSpace(modifiedMessage)) { continue; }
|
||||
}
|
||||
break;
|
||||
case ChatMessageType.Dead:
|
||||
//character still alive -> don't send
|
||||
if (client != senderClient && client.Character != null && !client.Character.IsDead) continue;
|
||||
if (client != senderClient && client.Character != null && !client.Character.IsDead) { continue; }
|
||||
break;
|
||||
case ChatMessageType.Private:
|
||||
//private msg sent to someone else than this client -> don't send
|
||||
if (client != targetClient && client != senderClient) continue;
|
||||
if (client != targetClient && client != senderClient) { continue; }
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3241,11 +3273,17 @@ namespace Barotrauma.Networking
|
||||
//too far to hear the msg -> don't send
|
||||
if (!client.Character.CanHearCharacter(message.Sender)) { continue; }
|
||||
}
|
||||
SendDirectChatMessage(new OrderChatMessage(message.Order, message.TargetCharacter, message.Sender, isNewOrder: message.IsNewOrder), client);
|
||||
SendDirectChatMessage(new OrderChatMessage(message.Order, message.Text, message.TargetCharacter, message.Sender, isNewOrder: message.IsNewOrder), client);
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(message.Text))
|
||||
{
|
||||
AddChatMessage(new OrderChatMessage(message.Order, message.TargetCharacter, message.Sender, isNewOrder: message.IsNewOrder));
|
||||
AddChatMessage(new OrderChatMessage(message.Order, message.Text, message.TargetCharacter, message.Sender, isNewOrder: message.IsNewOrder));
|
||||
if (ChatMessage.CanUseRadio(message.Sender, out var senderRadio))
|
||||
{
|
||||
//send to chat-linked wifi components
|
||||
Signal s = new Signal(message.Text, sender: message.Sender, source: senderRadio.Item);
|
||||
senderRadio.TransmitSignal(s, sentFromChat: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3521,9 +3559,7 @@ namespace Barotrauma.Networking
|
||||
//the client's previous character is no longer a remote player
|
||||
if (client.Character != null)
|
||||
{
|
||||
client.Character.IsRemotePlayer = false;
|
||||
client.Character.OwnerClientAddress = null;
|
||||
client.Character.OwnerClientName = null;
|
||||
client.Character.SetOwnerClient(null);
|
||||
}
|
||||
|
||||
if (newCharacter == null)
|
||||
@@ -3549,9 +3585,7 @@ namespace Barotrauma.Networking
|
||||
newCharacter.Info.Character = newCharacter;
|
||||
}
|
||||
|
||||
newCharacter.OwnerClientAddress = client.Connection.Endpoint.Address;
|
||||
newCharacter.OwnerClientName = client.Name;
|
||||
newCharacter.IsRemotePlayer = true;
|
||||
newCharacter.SetOwnerClient(client);
|
||||
newCharacter.Enabled = true;
|
||||
client.Character = newCharacter;
|
||||
CreateEntityEvent(newCharacter, new Character.ControlEventData(client));
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace Barotrauma.Networking
|
||||
segmentTable.StartNewSegment(ServerNetSegment.ChatMessage);
|
||||
msg.WriteUInt16(NetStateID);
|
||||
msg.WriteRangedInteger((int)ChatMessageType.Order, 0, Enum.GetValues(typeof(ChatMessageType)).Length - 1);
|
||||
msg.WriteString(Text);
|
||||
msg.WriteString(SenderName);
|
||||
msg.WriteBoolean(SenderClient != null);
|
||||
if (SenderClient != null)
|
||||
|
||||
+1
-1
@@ -246,7 +246,7 @@ namespace Barotrauma.Networking
|
||||
{
|
||||
case ConnectionInitialization.ContentPackageOrder:
|
||||
|
||||
DateTime timeNow = DateTime.UtcNow;
|
||||
SerializableDateTime timeNow = SerializableDateTime.UtcNow;
|
||||
structToSend = new ServerPeerContentPackageOrderPacket
|
||||
{
|
||||
ServerName = GameMain.Server.ServerName,
|
||||
|
||||
@@ -439,8 +439,7 @@ namespace Barotrauma.Networking
|
||||
}
|
||||
|
||||
clients[i].Character = character;
|
||||
character.OwnerClientAddress = clients[i].Connection.Endpoint.Address;
|
||||
character.OwnerClientName = clients[i].Name;
|
||||
character.SetOwnerClient(clients[i]);
|
||||
GameServer.Log(
|
||||
$"Respawning {GameServer.ClientLogName(clients[i])} ({clients[i].Connection.Endpoint}) as {characterInfos[i].Job.Name}", ServerLog.MessageType.Spawning);
|
||||
}
|
||||
|
||||
@@ -117,13 +117,13 @@ namespace Barotrauma
|
||||
|
||||
public void StopSubmarineVote(bool passed)
|
||||
{
|
||||
if (!(ActiveVote is SubmarineVote)) { return; }
|
||||
if (ActiveVote is not SubmarineVote) { return; }
|
||||
StopActiveVote(passed);
|
||||
}
|
||||
|
||||
public void StopMoneyTransferVote(bool passed)
|
||||
{
|
||||
if (!(ActiveVote is TransferVote)) { return; }
|
||||
if (ActiveVote is not TransferVote) { return; }
|
||||
StopActiveVote(passed);
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ namespace Barotrauma
|
||||
GameMain.Server.UpdateVoteStatus(checkActiveVote: false);
|
||||
}
|
||||
|
||||
private void StartOrEnqueueVote(IVote vote)
|
||||
private static void StartOrEnqueueVote(IVote vote)
|
||||
{
|
||||
if (ActiveVote == null)
|
||||
{
|
||||
@@ -198,9 +198,9 @@ namespace Barotrauma
|
||||
|
||||
ActiveVote.Timer += deltaTime;
|
||||
|
||||
if (ActiveVote.Timer >= GameMain.NetworkMember.ServerSettings.VoteTimeout)
|
||||
var inGameClients = GameMain.Server.ConnectedClients.Where(c => c.InGame);
|
||||
if (ActiveVote.Timer >= GameMain.NetworkMember.ServerSettings.VoteTimeout || inGameClients.Count() == 1)
|
||||
{
|
||||
var inGameClients = GameMain.Server.ConnectedClients.Where(c => c.InGame);
|
||||
var eligibleClients = inGameClients.Where(c => c != ActiveVote.VoteStarter);
|
||||
|
||||
// Do not take unanswered into account for total
|
||||
@@ -216,7 +216,7 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetVotes(IEnumerable<Client> connectedClients, bool resetKickVotes)
|
||||
public static void ResetVotes(IEnumerable<Client> connectedClients, bool resetKickVotes)
|
||||
{
|
||||
foreach (Client client in connectedClients)
|
||||
{
|
||||
@@ -254,7 +254,14 @@ namespace Barotrauma
|
||||
string modeIdentifier = inc.ReadString();
|
||||
GameModePreset mode = GameModePreset.List.Find(gm => gm.Identifier == modeIdentifier);
|
||||
if (mode == null || !mode.Votable) { break; }
|
||||
var prevHighestVoted = HighestVoted<GameModePreset>(VoteType.Mode, GameMain.Server.ConnectedClients);
|
||||
sender.SetVote(voteType, mode);
|
||||
var newHighestVoted = HighestVoted<GameModePreset>(VoteType.Mode, GameMain.Server.ConnectedClients);
|
||||
if (prevHighestVoted != newHighestVoted)
|
||||
{
|
||||
GameMain.NetLobbyScreen.SelectedModeIdentifier = mode.Identifier;
|
||||
GameMain.NetLobbyScreen.LastUpdateID++;
|
||||
}
|
||||
break;
|
||||
case VoteType.EndRound:
|
||||
if (!sender.HasSpawned) { return; }
|
||||
|
||||
@@ -59,6 +59,7 @@ namespace Barotrauma
|
||||
get { return GameModes[SelectedModeIndex].Identifier; }
|
||||
set
|
||||
{
|
||||
if (SelectedModeIdentifier == value) { return; }
|
||||
for (int i = 0; i < GameModes.Length; i++)
|
||||
{
|
||||
if (GameModes[i].Identifier == value)
|
||||
@@ -127,9 +128,11 @@ namespace Barotrauma
|
||||
{
|
||||
LevelSeed = ToolBox.RandomSeed(8);
|
||||
|
||||
subs = SubmarineInfo.SavedSubmarines.Where(s => s.Type == SubmarineType.Player && !s.HasTag(SubmarineTag.HideInMenus)).ToList();
|
||||
subs = SubmarineInfo.SavedSubmarines
|
||||
.Where(s => s.Type == SubmarineType.Player && !s.HasTag(SubmarineTag.HideInMenus))
|
||||
.ToList();
|
||||
|
||||
if (subs == null || subs.Count() == 0)
|
||||
if (subs == null || subs.Count == 0)
|
||||
{
|
||||
throw new Exception("No submarines are available.");
|
||||
}
|
||||
@@ -156,7 +159,7 @@ namespace Barotrauma
|
||||
GameModes = GameModePreset.List.ToArray();
|
||||
}
|
||||
|
||||
private List<SubmarineInfo> subs;
|
||||
private readonly List<SubmarineInfo> subs;
|
||||
public IReadOnlyList<SubmarineInfo> GetSubList() => subs;
|
||||
|
||||
public string LevelSeed
|
||||
@@ -192,7 +195,7 @@ namespace Barotrauma
|
||||
public override void Select()
|
||||
{
|
||||
base.Select();
|
||||
GameMain.Server.Voting.ResetVotes(GameMain.Server.ConnectedClients, resetKickVotes: false);
|
||||
Voting.ResetVotes(GameMain.Server.ConnectedClients, resetKickVotes: false);
|
||||
if (SelectedMode != GameModePreset.MultiPlayerCampaign && GameMain.GameSession?.GameMode is CampaignMode && Selected == this)
|
||||
{
|
||||
GameMain.GameSession = null;
|
||||
|
||||
Reference in New Issue
Block a user