(Feat) Add Network Body
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
using FishNet.Object;
|
||||
using FishNet.Object.Synchronizing;
|
||||
using Steamworks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ashwild.Network
|
||||
{
|
||||
/// <summary>
|
||||
/// Announces this player's arrival and departure to every other client's presence feed. Lives on
|
||||
/// the networked player prefab (like PlayerNameTag) and is NOT owner-gated — remote copies must run
|
||||
/// it so they can report their own despawn as a "left".
|
||||
///
|
||||
/// Join is server-driven: the owner submits its Steam name, the server stores it and fires a
|
||||
/// one-shot ObserversRpc to whoever is watching right now. Because the RPC isn't buffered, a client
|
||||
/// joining a busy room never replays the joins that happened before it arrived — no startup burst.
|
||||
/// Leave is client-detected: when a player's copy despawns (disconnect), each remaining client reads
|
||||
/// the replicated name and reports it. The feed UI itself suppresses the departure storm that fires
|
||||
/// when the local player is the one leaving the session.
|
||||
/// </summary>
|
||||
[DisallowMultipleComponent]
|
||||
public class SessionPresenceNotifier : NetworkBehaviour
|
||||
{
|
||||
#region Networked State
|
||||
|
||||
/// <summary>
|
||||
/// The owner's display name, written by the server so every client can label this player's
|
||||
/// "left" message once the copy despawns and the owner is already gone.
|
||||
/// </summary>
|
||||
private readonly SyncVar<string> displayName = new SyncVar<string>();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Network Lifecycle
|
||||
|
||||
/// <summary>
|
||||
/// On the owning client, publishes the local Steam persona name so the server can announce the join.
|
||||
/// </summary>
|
||||
public override void OnStartClient()
|
||||
{
|
||||
base.OnStartClient();
|
||||
|
||||
if (!base.IsOwner) return;
|
||||
|
||||
if (!SteamManager.Initialized)
|
||||
{
|
||||
Debug.LogError($"[SessionPresence] '{name}' — Steam not initialized, cannot announce join.", this);
|
||||
return;
|
||||
}
|
||||
|
||||
SubmitPresenceServerRpc(SteamFriends.GetPersonaName());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A player's copy is despawning on this client. On non-owner copies that means a remote player
|
||||
/// left the session, so report it; the owner never reports its own departure. Gated on the local
|
||||
/// client still running so that OUR own disconnect — which despawns every copy at once — doesn't
|
||||
/// announce the whole room leaving.
|
||||
/// </summary>
|
||||
public override void OnStopClient()
|
||||
{
|
||||
base.OnStopClient();
|
||||
|
||||
if (base.IsOwner || !base.IsClientStarted) return;
|
||||
|
||||
string playerName = displayName.Value;
|
||||
if (!string.IsNullOrEmpty(playerName))
|
||||
SessionPresenceEvents.RaisePlayerLeft(playerName);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Replication
|
||||
|
||||
/// <summary>
|
||||
/// Server-side: records the owner's name and announces the join once to the current observers.
|
||||
/// </summary>
|
||||
[ServerRpc]
|
||||
private void SubmitPresenceServerRpc(string persona)
|
||||
{
|
||||
displayName.Value = persona;
|
||||
AnnounceJoinObserversRpc(persona);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires on every client observing this player at join time; each reports it to its feed,
|
||||
/// except the owner who shouldn't be told they joined their own session.
|
||||
/// </summary>
|
||||
[ObserversRpc]
|
||||
private void AnnounceJoinObserversRpc(string persona)
|
||||
{
|
||||
if (base.IsOwner) return;
|
||||
SessionPresenceEvents.RaisePlayerJoined(persona);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user