Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 28 additions & 38 deletions MlapiClient.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
using Dissonance.Networking;
using MLAPI;
using MLAPI.Messaging;
using MLAPI.Serialization.Pooled;
using MLAPI.Transports.UNET;
using Unity.Netcode;
using System;
using System.IO;
using UnityEngine;
using Allocator = Unity.Collections.Allocator;

public class MlapiClient : BaseClient<MlapiServer, MlapiClient, MlapiConn>
{
Expand All @@ -19,66 +15,60 @@ public MlapiClient(MlapiCommsNetwork network) : base(network)
public override void Connect()
{
// Register receiving packets on the client from the server
CustomMessagingManager.RegisterNamedMessageHandler("DissonanceToClient", (senderClientId, stream) =>
{
Int32 length = stream.Length > Int32.MaxValue ? Int32.MaxValue : Convert.ToInt32(stream.Length);
Byte[] buffer = new Byte[length];
stream.Read(buffer, 0, length);

base.NetworkReceivedPacket(new ArraySegment<byte>(buffer));
});
NetworkManager.Singleton.CustomMessagingManager.RegisterNamedMessageHandler("DissonanceToClient", OnDissonanceToClient);
Connected();
}

protected void OnDissonanceToClient(ulong id, FastBufferReader reader)
{
reader.ReadValueSafe(out int length);
Byte[] buffer = new Byte[length];
reader.ReadBytesSafe(ref buffer, length);

base.NetworkReceivedPacket(new ArraySegment<byte>(buffer));
}

protected override void ReadMessages()
{

}

protected override void SendReliable(ArraySegment<byte> packet)
{
if (NetworkingManager.Singleton.IsHost)
if (NetworkManager.Singleton.IsServer)
{
// As we are the host in this scenario we should send the packet directly to the server rather than over the network and avoid loopback issues
// As we are the host in this scenario we should send the packet directly to the server rather than over the network and avoid loop-back issues
_network.server.NetworkReceivedPacket(new MlapiConn(), packet);
}
else
{

using (PooledBitStream stream = PooledBitStream.Get())
{
using (PooledBitWriter writer = PooledBitWriter.Get(stream))
{
for (var i = 0; i < packet.Count; i++)
{
writer.WriteByte(packet.Array[i + packet.Offset]);
}
CustomMessagingManager.SendNamedMessage("DissonanceToServer", NetworkingManager.Singleton.ServerClientId, stream, "MLAPI_ANIMATION_UPDATE");
}
using (FastBufferWriter writer = new FastBufferWriter(packet.Count + 4, Allocator.TempJob))
{
writer.WriteValueSafe(packet.Count);
writer.WriteBytesSafe(packet.Array, packet.Count, packet.Offset);

NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("DissonanceToServer",
NetworkManager.Singleton.ServerClientId, writer, NetworkDelivery.Reliable);
}
}
}

protected override void SendUnreliable(ArraySegment<byte> packet)
{
if (NetworkingManager.Singleton.IsHost)
if (NetworkManager.Singleton.IsServer)
{
// As we are the host in this scenario we should send the packet directly to the server rather than over the network and avoid loopback issues
_network.server.NetworkReceivedPacket(new MlapiConn(), packet);
}
else
{
using (FastBufferWriter writer = new FastBufferWriter(packet.Count + 4, Allocator.TempJob))
{
writer.WriteValueSafe(packet.Count);
writer.WriteBytesSafe(packet.Array, packet.Count, packet.Offset);

using (PooledBitStream stream = PooledBitStream.Get())
{
using (PooledBitWriter writer = PooledBitWriter.Get(stream))
{
for (var i = 0; i < packet.Count; i++)
{
writer.WriteByte(packet.Array[i + packet.Offset]);
}
CustomMessagingManager.SendNamedMessage("DissonanceToServer", NetworkingManager.Singleton.ServerClientId, stream, "MLAPI_TIME_SYNC");
}
NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("DissonanceToServer",
NetworkManager.Singleton.ServerClientId, writer, NetworkDelivery.Unreliable);
}
}

Expand Down
10 changes: 5 additions & 5 deletions MlapiCommsNetwork.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using Dissonance;
using Dissonance.Networking;
using JetBrains.Annotations;
using MLAPI;
using Unity.Netcode;

public class MlapiCommsNetwork
: BaseCommsNetwork<
Expand Down Expand Up @@ -39,13 +39,13 @@ protected override void Update()
if (IsInitialized)
{
// Check if the MLAPI is ready
var networkActive = NetworkingManager.Singleton.isActiveAndEnabled &&
(NetworkingManager.Singleton.IsClient || NetworkingManager.Singleton.IsHost);
var networkActive = NetworkManager.Singleton.isActiveAndEnabled &&
(NetworkManager.Singleton.IsClient || NetworkManager.Singleton.IsServer);
if (networkActive)
{
// Check what mode the MLAPI is in
var server = NetworkingManager.Singleton.IsHost;
var client = NetworkingManager.Singleton.IsClient;
var server = NetworkManager.Singleton.IsServer;
var client = NetworkManager.Singleton.IsClient;

// Check what mode Dissonance is in and if
// they're different then call the correct method
Expand Down
2 changes: 1 addition & 1 deletion UNetCommsNetworkEditor.cs → MlapiCommsNetworkEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#if UNITY_EDITOR

[CustomEditor(typeof(MlapiCommsNetwork))]
public class UNetCommsNetworkEditor
public class MlapiCommsNetworkEditor
: Dissonance.Editor.BaseDissonnanceCommsNetworkEditor<
MlapiCommsNetwork,
MlapiServer,
Expand Down
File renamed without changes.
174 changes: 174 additions & 0 deletions MlapiPlayer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
using UnityEngine;
using Unity.Netcode;
using Dissonance;

/// <summary>
/// When added to the player prefab, allows Dissonance to automatically track
/// the location of remote players for positional audio for games using the
/// MLAPI / NFGO
/// </summary>
[RequireComponent(typeof (NetworkObject))]
public class MlapiPlayer : NetworkBehaviour, IDissonancePlayer
{
private static readonly Log Log = Logs.Create(LogCategory.Network, "HLAPI Player Component");

private DissonanceComms _comms;

public bool IsTracking { get; private set; }

/// <summary>
/// The name of the player
/// </summary>
///
private string _playerId;
public string PlayerId { get { return _playerId; } }

public Vector3 Position
{
get { return transform.position; }
}

public Quaternion Rotation
{
get { return transform.rotation; }
}

public NetworkPlayerType Type
{
get
{
if (_comms == null || _playerId == null)
return NetworkPlayerType.Unknown;
return _comms.LocalPlayerName.Equals(_playerId) ? NetworkPlayerType.Local : NetworkPlayerType.Remote;
}
}

public override void OnDestroy()
{
base.OnDestroy();
if (_comms != null)
_comms.LocalPlayerNameChanged -= SetPlayerName;
}

public void OnEnable()
{
_comms = FindObjectOfType<DissonanceComms>();
}

public void OnDisable()
{
if (IsTracking)
StopTracking();
}

public override void OnNetworkSpawn()
{
base.OnNetworkSpawn();

if(IsClient)
{
OnStartClient();

if (IsLocalPlayer)
OnStartLocalPlayer();
}
}

protected void OnStartLocalPlayer()
{
var comms = FindObjectOfType<DissonanceComms>();
if (comms == null)
{
throw Log.CreateUserErrorException(
"cannot find DissonanceComms component in scene",
"not placing a DissonanceComms component on a game object in the scene",
"",
"9A79FDCB-263E-4124-B54D-67EDA39C09A5"
);
}

Log.Debug("Tracking `OnStartLocalPlayer` Name={0}", comms.LocalPlayerName);

// This method is called on the client which has control authority over this object. This will be the local client of whichever player we are tracking.
if (comms.LocalPlayerName != null)
SetPlayerName(comms.LocalPlayerName);

//Subscribe to future name changes (this is critical because we may not have run the initial set name yet and this will trigger that initial call)
comms.LocalPlayerNameChanged += SetPlayerName;
}

private void SetPlayerName(string playerName)
{
//We need the player name to be set on all the clients and then tracking to be started (on each client).
//To do this we send a command from this client, informing the server of our name. The server will pass this on to all the clients (with an RPC)
// Client -> Server -> Client

//We need to stop and restart tracking to handle the name change
if (IsTracking)
StopTracking();

//Perform the actual work
_playerId = playerName;
StartTracking();

//Inform the server the name has changed
if (IsLocalPlayer)
SetPlayerNameServerRpc(playerName);
}

protected void OnStartClient()
{
//A client is starting. Start tracking if the name has been properly initialised.
if (!string.IsNullOrEmpty(PlayerId))
StartTracking();
}

/// <summary>
/// Invoking on client will cause it to run on the server
/// </summary>
/// <param name="playerName"></param>
[ServerRpc]
private void SetPlayerNameServerRpc(string playerName)
{
_playerId = playerName;

//Now call the RPC to inform clients they need to handle this changed value
SetPlayerNameClientRpc(playerName);
}

/// <summary>
/// Invoking on the server will cause it to run on all the clients
/// </summary>
/// <param name="playerName"></param>
[ClientRpc]
private void SetPlayerNameClientRpc(string playerName)
{
//received a message from server (on all clients). If this is not the local player then apply the change
if (!IsLocalPlayer)
SetPlayerName(playerName);
}

private void StartTracking()
{
if (IsTracking)
throw Log.CreatePossibleBugException("Attempting to start player tracking, but tracking is already started", "B7D1F25E-72AF-4E93-8CFF-90CEBEAC68CF");

if (_comms != null)
{
_comms.TrackPlayerPosition(this);
IsTracking = true;
}
}

private void StopTracking()
{
if (!IsTracking)
throw Log.CreatePossibleBugException("Attempting to stop player tracking, but tracking is not started", "EC5C395D-B544-49DC-B33C-7D7533349134");

if (_comms != null)
{
_comms.StopTracking(this);
IsTracking = false;
}
}
}
11 changes: 11 additions & 0 deletions MlapiPlayer.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading