My custom networking (Server is a player) has a connection array holding data about clients. If someone is hosting as a server, both the Dissonance server and client classes will run. How would I move the bytes then if my network doesn't work like this. I suppose I keep a reference to the custom comms network and to the custom server, then send the bytes directly without any networking but I have to pass a CustomPeer and that peer includes an IPEndPoint and or SteamConnection (NetworkReceivedPacket needs CustomPeer for Custom Server). I have spent a lot of time reading through the custom networking tutorial, and preparing everything to make this work. However, I understand my setup and not this very well. I have been in the source code many times over. I wouldn't be surprised if I have made more than a handful of mistakes, any help would be appreciated.
#define USING_DISSONANCE
using Dissonance;
using Dissonance.Networking;
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Net;
using UnityEngine;
using static NetworkManager;
using static PublicStatics;
using static SteamworksManager;
public class CustomCommsNetwork: BaseCommsNetwork<CustomServer, CustomClient, CustomPeer, Unit, Unit> {
#region Declares
//Declare privates
private CustomServer customServer = null;
private CustomClient customClient = null;
//Declare public properties
public CustomServer GetCustomServer { get => customServer; }
public CustomClient GetCustomClient { get => customClient; }
#endregion
#region Constructor
public CustomCommsNetwork() { } //Do not add parameters
#endregion
#region Public functions
protected override CustomServer CreateServer(Unit details) {
customServer = new CustomServer(this, details);
return customServer;
}
protected override CustomClient CreateClient(Unit details) {
customClient = new CustomClient(this, details);
return customClient;
}
#if USING_DISSONANCE
protected override void Initialize() {
Debug.Log("Dissonance is about to initialize.");
base.Initialize();
}
protected override void Update() {
Debug.Log("Dissonance update is running!");
if (IsInitialized) {
bool networkActive = NetworkIsActive();
if (networkActive) {
bool server = networkManager.SubSystem.IsHost;
bool client = networkManager.SubSystem.IsHost;
// Check what mode Dissonance is in and if
// they're different then call the correct method
if (Mode.IsServerEnabled() != server || Mode.IsClientEnabled() != client)
{
// HLAPI is server and client, so run as a non-dedicated
// host (passing in the correct parameters)
if (server && client)
RunAsHost(Unit.None, Unit.None);
// HLAPI is just a server, so run as a dedicated host
else if (server)
RunAsDedicatedServer(Unit.None);
// HLAPI is just a client, so run as a client
else if (client)
RunAsClient(Unit.None);
}
}
else if (Mode != NetworkMode.None)
{
//Network is not active, make sure Dissonance is not active
Stop();
}
}
base.Update();
#region Functions
bool NetworkIsActive() {
if (networkManager.Network != null) {
if (gameCanvas.ScreenViewState == GameCanvas.ScreenViewStates.Lobby ||
gameCanvas.ScreenViewState == GameCanvas.ScreenViewStates.LoadingSceneForGame ||
gameCanvas.ScreenViewState == GameCanvas.ScreenViewStates.UnloadingSceneForLobby ||
gameCanvas.ScreenViewState == GameCanvas.ScreenViewStates.GameScene ||
gameCanvas.ScreenViewState == GameCanvas.ScreenViewStates.UnloadingSceneForGame) {
//For now return true, until sure if more code is necessary here
return true;
}
}
return false;
}
#endregion
}
#endif
#endregion
}
public class CustomServer: BaseServer<CustomServer, CustomClient, CustomPeer> {
#region Declares
//Declare
private ConcurrentQueue<Packet> packets = new ConcurrentQueue<Packet>(); //Convert to non allocating later
#endregion
#region Classes
private class Packet {
public CustomPeer customPeer;
public ArraySegment<byte> packet;
public Packet(CustomPeer customPeer, ArraySegment<byte> packet) {
this.customPeer = customPeer;
this.packet = packet;
}
}
#endregion
public CustomServer(CustomCommsNetwork network, Unit details) { }
public void EnqueuePacket(CustomPeer customPeer, ArraySegment<byte> packet) {
packets.Enqueue(new Packet(customPeer, packet));
}
public override void Connect() {
}
public override void Disconnect() {
}
protected override void ReadMessages() {
int count = packets.Count;
for (int i = 0; i < count; i++) {
packets.LineBlockingDequeue(out Packet packet);
NetworkReceivedPacket(packet.customPeer, packet.packet);
}
}
protected override void SendReliable(CustomPeer destination, ArraySegment<byte> packet) {
//Declare
UDPSubSystem.Host host = networkManager.Host;
UDPSubSystem.Connection connection = GetConnection(host, destination, out ushort slotIndex);
byte localHeaderSize = UDPSubSystem.PUBLIC_CONSTANTS.PACKET.SIZE.OPCODE + UDPSubSystem.PUBLIC_CONSTANTS.DATA_TYPE.SIZE.USHORT +
UDPSubSystem.PUBLIC_CONSTANTS.DATA_TYPE.SIZE.USHORT;
byte[] data = new byte[localHeaderSize + packet.Count]; //Remove GC later
byte[] opcode = OpcodesClient.GetOpcode(OpcodesClient.Opcodes.R_DissonanceMicrophone);
byte[] slotIndexBytes = BitConverter.GetBytes(slotIndex); //Remove bitconverter later
byte[] length = BitConverter.GetBytes((ushort)packet.Count); //Remove bitconverter later
data[0] = opcode[0];
data[1] = opcode[1];
data[2] = slotIndexBytes[0];
data[3] = slotIndexBytes[1];
data[4] = length[0];
data[5] = length[1];
int count = packet.Count;
for (int i = 0; i < count; i++) {
data[i + localHeaderSize] = packet[i];
}
host.WriteData(connection, data);
}
//Write better later
private UDPSubSystem.Connection GetConnection(UDPSubSystem.Host host, CustomPeer destination, out ushort slotIndex) {
switch (networkManager.NetworkingSocket) {
case NetworkingSockets.SteamSocket:
for (int i = 0; i < host.connections.Length; i++) {
if (host.connections[i].steamConnection.Equals(destination.steamConnection)) {
slotIndex = (ushort)(i + 1);
return host.connections[i];
}
}
break;
default: //UDPSocket
for (int i = 0; i < host.connections.Length; i++) {
if (host.connections[i].ipEndPoint.Equals(destination.ipEndPoint)) {
slotIndex = (ushort)(i + 1);
return host.connections[i];
}
}
break;
}
//Set, should never get here
slotIndex = 1;
return host.connections[0];
}
protected override void SendUnreliable(CustomPeer destination, ArraySegment<byte> packet) {
UDPSubSystem.Host host = networkManager.Host;
UDPSubSystem.Connection connection = GetConnection(host, destination, out ushort slotIndex);
byte localHeaderSize = UDPSubSystem.PUBLIC_CONSTANTS.PACKET.SIZE.OPCODE + UDPSubSystem.PUBLIC_CONSTANTS.DATA_TYPE.SIZE.USHORT +
UDPSubSystem.PUBLIC_CONSTANTS.DATA_TYPE.SIZE.USHORT;
byte[] data = new byte[localHeaderSize + packet.Count]; //Remove GC later
byte[] opcode = OpcodesClient.GetOpcode(OpcodesClient.Opcodes.U_DissonanceMicrophone);
byte[] slotIndexBytes = BitConverter.GetBytes(slotIndex); //Remove bitconverter later
byte[] length = BitConverter.GetBytes((ushort)packet.Count); //Remove bitconverter later
data[0] = opcode[0];
data[1] = opcode[1];
data[2] = slotIndexBytes[0];
data[3] = slotIndexBytes[1];
data[4] = length[0];
data[5] = length[1];
int count = packet.Count;
for (int i = 0; i < count; i++) {
data[i + localHeaderSize] = packet[i];
}
host.WriteData(connection, data);
}
}
public class CustomClient : BaseClient<CustomServer, CustomClient, CustomPeer> {
#region Declares
private ConcurrentQueue<ArraySegment<byte>> packets = new ConcurrentQueue<ArraySegment<byte>>(); //Convert to non allocating later
private CustomCommsNetwork customCommsNetwork = null;
#endregion
public CustomClient(CustomCommsNetwork network, Unit details) : base(network) {
customCommsNetwork = network;
}
public void EnqueuePacket(ArraySegment<byte> packet) {
packets.Enqueue(packet);
}
public override void Connect() {
base.Connected();
}
protected override void ReadMessages() {
int count = packets.Count;
for (int i = 0; i < count; i++) {
packets.LineBlockingDequeue(out ArraySegment<byte> packet);
NetworkReceivedPacket(packet);
}
}
protected override void SendReliable(ArraySegment<byte> packet) {
if (networkManager.SubSystem.IsHost) {
customCommsNetwork.GetCustomServer.EnqueuePacket(new CustomPeer(), packet);
} else {
UDPSubSystem.Client client = networkManager.Client;
byte localHeaderSize = UDPSubSystem.PUBLIC_CONSTANTS.PACKET.SIZE.OPCODE + UDPSubSystem.PUBLIC_CONSTANTS.DATA_TYPE.SIZE.USHORT;
byte[] data = new byte[localHeaderSize + packet.Count]; //Remove GC later
byte[] opcode = OpcodesHost.GetOpcode(OpcodesHost.Opcodes.R_DissonanceMicrophone);
byte[] length = BitConverter.GetBytes((ushort)packet.Count); //Remove bitconverter later
data[0] = opcode[0];
data[1] = opcode[1];
data[2] = length[0];
data[3] = length[1];
int count = packet.Count;
for (int i = 0; i < count; i++) {
data[i + localHeaderSize] = packet[i];
}
client.WriteData(client.connections[0], data);
}
}
protected override void SendUnreliable(ArraySegment<byte> packet) {
if (networkManager.SubSystem.IsHost) {
customCommsNetwork.GetCustomServer.EnqueuePacket(new CustomPeer(), packet);
} else {
UDPSubSystem.Client client = networkManager.Client;
byte localHeaderSize = UDPSubSystem.PUBLIC_CONSTANTS.PACKET.SIZE.OPCODE + UDPSubSystem.PUBLIC_CONSTANTS.DATA_TYPE.SIZE.USHORT;
byte[] data = new byte[localHeaderSize + packet.Count]; //Remove GC later
byte[] opcode = OpcodesHost.GetOpcode(OpcodesHost.Opcodes.U_DissonanceMicrophone);
byte[] length = BitConverter.GetBytes((ushort)packet.Count); //Remove bitconverter later
data[0] = opcode[0];
data[1] = opcode[1];
data[2] = length[0];
data[3] = length[1];
int count = packet.Count;
for (int i = 0; i < count; i++) {
data[i + localHeaderSize] = packet[i];
}
client.WriteData(client.connections[0], data);
}
}
}
public struct CustomPeer : IEquatable<CustomPeer> {
public IPEndPoint ipEndPoint;
public SteamworksNetworking.Connection steamConnection;
public CustomPeer(IPEndPoint ipEndPoint, SteamworksNetworking.Connection steamConnection) {
this.ipEndPoint = ipEndPoint;
this.steamConnection = steamConnection;
}
public bool Equals(CustomPeer other) {
return
Equals(ipEndPoint, other.ipEndPoint) &&
steamConnection.connection == other.steamConnection.connection &&
EqualityComparer<User>.Default.Equals(steamConnection.user, other.steamConnection.user);
}
public override bool Equals(object obj) {
return obj is CustomPeer other && Equals(other);
}
public override int GetHashCode() {
return HashCode.Combine(ipEndPoint, steamConnection.connection, steamConnection.user);
}
public override string ToString() {
return $"IPEndpoint[{ipEndPoint}, Steam Connection={steamConnection.connection}, Steam User={steamConnection.user}]";
}
}
public struct CustomServerParam {}
public struct CustomClientParam {}
My custom networking (Server is a player) has a connection array holding data about clients. If someone is hosting as a server, both the Dissonance server and client classes will run. How would I move the bytes then if my network doesn't work like this. I suppose I keep a reference to the custom comms network and to the custom server, then send the bytes directly without any networking but I have to pass a CustomPeer and that peer includes an IPEndPoint and or SteamConnection (NetworkReceivedPacket needs CustomPeer for Custom Server). I have spent a lot of time reading through the custom networking tutorial, and preparing everything to make this work. However, I understand my setup and not this very well. I have been in the source code many times over. I wouldn't be surprised if I have made more than a handful of mistakes, any help would be appreciated.