Skip to content

Commit

Permalink
Move player join broadcast to after initial sync completed, and ensur…
Browse files Browse the repository at this point in the history
…e player entity is spawned in priority
  • Loading branch information
tornac1234 authored and Jannify committed Feb 8, 2024
1 parent 151a2bb commit 82671c4
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 62 deletions.
Original file line number Diff line number Diff line change
@@ -1,30 +1,33 @@
using System.Collections.Generic;
using System.Linq;
using System.Collections;
using NitroxClient.Communication.Packets.Processors.Abstract;
using NitroxClient.GameLogic;
using NitroxModel.Packets;
using NitroxModel_Subnautica.DataStructures;
using UWE;

namespace NitroxClient.Communication.Packets.Processors
namespace NitroxClient.Communication.Packets.Processors;

public class PlayerJoinedMultiplayerSessionProcessor : ClientPacketProcessor<PlayerJoinedMultiplayerSession>
{
public class PlayerJoinedMultiplayerSessionProcessor : ClientPacketProcessor<PlayerJoinedMultiplayerSession>
{
private readonly PlayerManager playerManager;
private readonly PlayerManager playerManager;
private readonly Entities entities;

public PlayerJoinedMultiplayerSessionProcessor(PlayerManager playerManager)
{
this.playerManager = playerManager;
}
public PlayerJoinedMultiplayerSessionProcessor(PlayerManager playerManager, Entities entities)
{
this.playerManager = playerManager;
this.entities = entities;
}

public override void Process(PlayerJoinedMultiplayerSession packet)
{
List<TechType> techTypes = packet.EquippedTechTypes.Select(techType => techType.ToUnity()).ToList();
List<Pickupable> items = new List<Pickupable>();
public override void Process(PlayerJoinedMultiplayerSession packet)
{
CoroutineHost.StartCoroutine(SpawnRemotePlayer(packet));
}

playerManager.Create(packet.PlayerContext);
private IEnumerator SpawnRemotePlayer(PlayerJoinedMultiplayerSession packet)
{
playerManager.Create(packet.PlayerContext);
yield return entities.SpawnEntityAsync(packet.PlayerWorldEntity, true, true);

Log.Info($"{packet.PlayerContext.PlayerName} joined the game");
Log.InGame(Language.main.Get("Nitrox_PlayerJoined").Replace("{PLAYER}", packet.PlayerContext.PlayerName));
}
Log.Info($"{packet.PlayerContext.PlayerName} joined the game");
Log.InGame(Language.main.Get("Nitrox_PlayerJoined").Replace("{PLAYER}", packet.PlayerContext.PlayerName));
}
}
4 changes: 2 additions & 2 deletions NitroxClient/GameLogic/Entities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -225,9 +225,9 @@ public IEnumerator SpawnBatchAsync(List<Entity> batch, bool forceRespawn = false
}
}

public IEnumerator SpawnEntityAsync(Entity entity, bool forceRespawn = false)
public IEnumerator SpawnEntityAsync(Entity entity, bool forceRespawn = false, bool skipFrames = false)
{
return SpawnBatchAsync(new() { entity }, forceRespawn, skipFrames: false);
return SpawnBatchAsync(new() { entity }, forceRespawn, skipFrames);
}

public void CleanupExistingEntities(List<Entity> dirtyEntities)
Expand Down
28 changes: 13 additions & 15 deletions NitroxModel/Packets/PlayerJoinedMultiplayerSession.cs
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
using System;
using System.Collections.Generic;
using NitroxModel.DataStructures;
using NitroxModel.DataStructures.GameLogic;
using NitroxModel.DataStructures.GameLogic.Entities;
using NitroxModel.DataStructures.Util;
using NitroxModel.MultiplayerSession;

namespace NitroxModel.Packets
namespace NitroxModel.Packets;

[Serializable]
public class PlayerJoinedMultiplayerSession : Packet
{
[Serializable]
public class PlayerJoinedMultiplayerSession : Packet
{
public PlayerContext PlayerContext { get; }
public Optional<NitroxId> SubRootId { get; }
public List<NitroxTechType> EquippedTechTypes { get; }
public PlayerContext PlayerContext { get; }
public Optional<NitroxId> SubRootId { get; }
public PlayerWorldEntity PlayerWorldEntity { get; }

public PlayerJoinedMultiplayerSession(PlayerContext playerContext, Optional<NitroxId> subRootId, List<NitroxTechType> equippedTechTypes)
{
PlayerContext = playerContext;
SubRootId = subRootId;
EquippedTechTypes = equippedTechTypes;
}
public PlayerJoinedMultiplayerSession(PlayerContext playerContext, Optional<NitroxId> subRootId, PlayerWorldEntity playerWorldEntity)
{
PlayerContext = playerContext;
SubRootId = subRootId;
PlayerWorldEntity = playerWorldEntity;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,6 @@ public override void Process(PlayerJoiningMultiplayerSession packet, NitroxConne
}

List<EquippedItemData> equippedItems = player.GetEquipment();
List<NitroxTechType> techTypes = equippedItems.Select(equippedItem => equippedItem.TechType).ToList();

PlayerJoinedMultiplayerSession playerJoinedPacket = new(player.PlayerContext, player.SubRootId, techTypes);
playerManager.SendPacketToOtherPlayers(playerJoinedPacket, player);

// Make players on localhost admin by default.
if (connection.Endpoint.Address.IsLocalhost())
Expand All @@ -61,14 +57,8 @@ public override void Process(PlayerJoiningMultiplayerSession packet, NitroxConne

List<NitroxId> simulations = world.EntitySimulation.AssignGlobalRootEntities(player).ToList();

if (wasBrandNewPlayer)
{
SetupPlayerEntity(player);
}
else
{
RespawnExistingEntity(player);
}
player.Entity = wasBrandNewPlayer ? SetupPlayerEntity(player) : RespawnExistingEntity(player); ;

List<GlobalRootEntity> globalRootEntities = world.WorldEntityManager.GetGlobalRootEntities(true);
bool isFirstPlayer = playerManager.GetConnectedPlayers().Count == 1;

Expand Down Expand Up @@ -105,29 +95,24 @@ private IEnumerable<PlayerContext> GetOtherPlayers(Player player)
.Select(p => p.PlayerContext);
}

private void SetupPlayerEntity(Player player)
private PlayerWorldEntity SetupPlayerEntity(Player player)
{
NitroxTransform transform = new(player.Position, player.Rotation, NitroxVector3.One);

PlayerWorldEntity playerEntity = new PlayerWorldEntity(transform, 0, null, false, player.GameObjectId, NitroxTechType.None, null, null, new List<Entity>());
entityRegistry.AddOrUpdate(playerEntity);
world.WorldEntityManager.TrackEntityInTheWorld(playerEntity);
playerManager.SendPacketToOtherPlayers(new SpawnEntities(playerEntity), player);
return playerEntity;
}

private void RespawnExistingEntity(Player player)
private PlayerWorldEntity RespawnExistingEntity(Player player)
{
Optional<Entity> playerEntity = entityRegistry.GetEntityById(player.PlayerContext.PlayerNitroxId);

if (playerEntity.HasValue)
{
playerManager.SendPacketToOtherPlayers(new SpawnEntities(playerEntity.Value, true), player);
}
else
if (entityRegistry.TryGetEntityById(player.PlayerContext.PlayerNitroxId, out PlayerWorldEntity playerWorldEntity))
{
Log.Error($"Unable to find player entity for {player.Name}. Re-creating one");
SetupPlayerEntity(player);
return playerWorldEntity;
}
Log.Error($"Unable to find player entity for {player.Name}. Re-creating one");
return SetupPlayerEntity(player);
}
}
}
10 changes: 10 additions & 0 deletions NitroxServer/GameLogic/PlayerManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,10 @@ public void FinishProcessingReservation(Player player = null)
{
initialSyncTimer.Dispose();
PlayerCurrentlyJoining = false;
if (player != null)
{
BroadcastPlayerJoined(player);
}

Log.Info($"Finished processing reservation. Remaining requests: {JoinQueue.Count}");

Expand Down Expand Up @@ -338,5 +342,11 @@ public IEnumerable<Player> ConnectedPlayers()
.Where(assetPackage => assetPackage.Player != null)
.Select(assetPackage => assetPackage.Player);
}

public void BroadcastPlayerJoined(Player player)
{
PlayerJoinedMultiplayerSession playerJoinedPacket = new(player.PlayerContext, player.SubRootId, player.Entity);
SendPacketToOtherPlayers(playerJoinedPacket, player);
}
}
}
6 changes: 4 additions & 2 deletions NitroxServer/Player.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
using System.Collections.Generic;
using NitroxModel.DataStructures;
using NitroxModel.DataStructures.GameLogic;
using NitroxModel.DataStructures.Unity;
using NitroxModel.DataStructures.GameLogic.Entities;
using NitroxModel.DataStructures.Unity;
using NitroxModel.DataStructures.Util;
using NitroxModel.MultiplayerSession;
using NitroxModel.Packets;
using NitroxModel.Packets.Processors.Abstract;
using NitroxServer.Communication;
using NitroxModel.Server;
using NitroxServer.Communication;

namespace NitroxServer
{
Expand Down Expand Up @@ -40,6 +40,8 @@ public class Player : IProcessorContext
public ThreadSafeDictionary<string, PingInstancePreference> PingInstancePreferences { get; set; }
public ThreadSafeList<int> PinnedRecipePreferences { get; set; }

public PlayerWorldEntity Entity { get; set; }

public Player(ushort id, string name, bool isPermaDeath, PlayerContext playerContext, NitroxConnection connection,
NitroxVector3 position, NitroxQuaternion rotation, NitroxId playerId, Optional<NitroxId> subRootId, Perms perms, PlayerStatsData stats, NitroxGameMode gameMode,
IEnumerable<NitroxTechType> usedItems, Optional<NitroxId>[] quickSlotsBindingIds,
Expand Down

0 comments on commit 82671c4

Please sign in to comment.