Files
Emberwild/Assets/GAME/Script/Network/NetworkPlayerLookup.cs
Mathew 78bfdf2828 Merge remote-tracking branch 'origin/feat/inport-props' into feat/craft-discovery
# Conflicts:
#	Assets/External/Animated PBR Chest Demo/Materials/WoodChest.mat
#	Packages/com.distantlands.cozy.core/Content/Integration/Import for BiRP.unitypackage.meta
#	Packages/com.distantlands.cozy.core/Content/Integration/Import for HDRP.unitypackage.meta
#	Packages/com.distantlands.cozy.core/Content/Integration/Import for URP.unitypackage.meta
2026-07-25 19:42:26 +02:00

49 lines
2.1 KiB
C#

using FishNet.Connection;
using FishNet.Object;
using Ashwild.Inventory;
namespace Ashwild.Network
{
/// <summary>
/// Server-side lookup of the player systems belonging to a connection. Every server-authoritative
/// interaction (pickup, harvest, chest, cooking station, build refund) needs the requesting player's
/// inventory, and they all used to resolve it through <c>conn.FirstObject</c>.
///
/// That is unsafe: a connection owns more than one NetworkObject (the build ghost is spawned with the
/// player as owner), FishNet stores them in an unordered <c>HashSet</c>, and it re-picks FirstObject
/// from that set whenever the current one is despawned. FirstObject can therefore resolve to the ghost
/// instead of the player — a null inventory, and a silently lost grant. Scanning the connection's
/// objects for the component we actually want removes the guesswork.
/// </summary>
public static class NetworkPlayerLookup
{
#region Public API
/// <summary>
/// Returns the inventory of the player owned by this connection, or null when the connection has
/// no player object (disconnecting, or not spawned yet).
/// </summary>
public static PlayerInventory ResolveInventory(NetworkConnection conn) => Resolve<PlayerInventory>(conn);
/// <summary>
/// Returns the first component of the requested type found on any NetworkObject this connection
/// owns. Checks FirstObject before scanning, since it is the right answer in the common case.
/// </summary>
public static T Resolve<T>(NetworkConnection conn) where T : class
{
if (conn == null) return null;
NetworkObject first = conn.FirstObject;
if (first != null && first.TryGetComponent(out T fromFirst)) return fromFirst;
foreach (NetworkObject nob in conn.Objects)
{
if (nob != null && nob.TryGetComponent(out T component)) return component;
}
return null;
}
#endregion
}
}