added RPC support 😲
parent
eeb539ba49
commit
bcd39cf601
|
|
@ -1,4 +1,8 @@
|
|||
using UnityEngine;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VelNet
|
||||
{
|
||||
|
|
@ -13,7 +17,7 @@ namespace VelNet
|
|||
/// </summary>
|
||||
protected void SendBytes(byte[] message, bool reliable = true)
|
||||
{
|
||||
networkObject.SendBytes(this, message, reliable);
|
||||
networkObject.SendBytes(this, false, message, reliable);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -21,12 +25,87 @@ namespace VelNet
|
|||
/// </summary>
|
||||
protected void SendBytesToGroup(string group, byte[] message, bool reliable = true)
|
||||
{
|
||||
networkObject.SendBytesToGroup(this, group, message, reliable);
|
||||
networkObject.SendBytesToGroup(this, false, group, message, reliable);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is called by <see cref="NetworkObject"/> when messages are received for this component
|
||||
/// </summary>
|
||||
public abstract void ReceiveBytes(byte[] message);
|
||||
|
||||
public void ReceiveRPC(byte[] message)
|
||||
{
|
||||
using MemoryStream mem = new MemoryStream(message);
|
||||
using BinaryReader reader = new BinaryReader(mem);
|
||||
byte methodIndex = reader.ReadByte();
|
||||
int length = reader.ReadInt32();
|
||||
byte[] parameterData = reader.ReadBytes(length);
|
||||
|
||||
MethodInfo[] mInfos = GetType().GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
Array.Sort(mInfos, (m1, m2) => string.Compare(m1.Name, m2.Name, StringComparison.Ordinal));
|
||||
try
|
||||
{
|
||||
mInfos[methodIndex].Invoke(this, length > 0 ? new object[] { parameterData } : Array.Empty<object>());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"Error processing received RPC {e}");
|
||||
}
|
||||
}
|
||||
|
||||
protected void SendRPCToGroup(string group, bool runLocally, string methodName, byte[] parameterData = null)
|
||||
{
|
||||
if (GenerateRPC(methodName, parameterData, out byte[] bytes)) return;
|
||||
|
||||
if (runLocally) ReceiveRPC(bytes);
|
||||
|
||||
networkObject.SendBytesToGroup(this, true, group, bytes, true);
|
||||
}
|
||||
|
||||
protected void SendRPC(string methodName, bool runLocally, byte[] parameterData = null)
|
||||
{
|
||||
if (GenerateRPC(methodName, parameterData, out byte[] bytes)) return;
|
||||
|
||||
if (networkObject.SendBytes(this, true, bytes, true))
|
||||
{
|
||||
// only run locally if we can successfully send
|
||||
if (runLocally) ReceiveRPC(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
private bool GenerateRPC(string methodName, byte[] parameterData, out byte[] bytes)
|
||||
{
|
||||
bytes = null;
|
||||
using MemoryStream mem = new MemoryStream();
|
||||
using BinaryWriter writer = new BinaryWriter(mem);
|
||||
|
||||
MethodInfo[] mInfos = GetType().GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
Array.Sort(mInfos, (m1, m2) => string.Compare(m1.Name, m2.Name, StringComparison.Ordinal));
|
||||
int methodIndex = mInfos.ToList().FindIndex(m => m.Name == methodName);
|
||||
switch (methodIndex)
|
||||
{
|
||||
case > 255:
|
||||
Debug.LogError("Too many methods in this class.");
|
||||
return true;
|
||||
case < 0:
|
||||
Debug.LogError("Can't find a method with that name.");
|
||||
return true;
|
||||
}
|
||||
|
||||
writer.Write((byte)methodIndex);
|
||||
if (parameterData != null)
|
||||
{
|
||||
writer.Write(parameterData.Length);
|
||||
writer.Write(parameterData);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.Write(0);
|
||||
}
|
||||
|
||||
bytes = mem.ToArray();
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.NetworkInformation;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
|
@ -40,52 +41,96 @@ namespace VelNet
|
|||
|
||||
public List<NetworkComponent> syncedComponents;
|
||||
|
||||
public void SendBytes(NetworkComponent component, byte[] message, bool reliable = true)
|
||||
/// <summary>
|
||||
/// Player is the new owner
|
||||
/// </summary>
|
||||
public Action<VelNetPlayer> OwnershipChanged;
|
||||
|
||||
public bool SendBytes(NetworkComponent component, bool isRpc, byte[] message, bool reliable = true)
|
||||
{
|
||||
if (!IsMine)
|
||||
// only needs to be owner if this isn't an RPC
|
||||
// RPC calls can be called by non-owner
|
||||
if (!IsMine && !isRpc)
|
||||
{
|
||||
Debug.LogError("Can't send message if owner is null or not local", this);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!VelNetManager.InRoom)
|
||||
{
|
||||
Debug.LogError("Can't send message if not in a room", this);
|
||||
return false;
|
||||
}
|
||||
|
||||
// send the message and an identifier for which component it belongs to
|
||||
if (!syncedComponents.Contains(component))
|
||||
{
|
||||
Debug.LogError("Can't send message if this component is not registered with the NetworkObject.", this);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
int index = syncedComponents.IndexOf(component);
|
||||
if (index < 0)
|
||||
int componentIndex = syncedComponents.IndexOf(component);
|
||||
switch (componentIndex)
|
||||
{
|
||||
case > 127:
|
||||
Debug.LogError("Too many components.", component);
|
||||
return false;
|
||||
case < 0:
|
||||
Debug.LogError("WAAAAAAAH. NetworkObject doesn't have a reference to this component.", component);
|
||||
}
|
||||
else
|
||||
{
|
||||
VelNetPlayer.SendMessage(this, (byte)index, message, reliable);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void SendBytesToGroup(NetworkComponent component, string group, byte[] message, bool reliable = true)
|
||||
byte componentByte = (byte)(componentIndex << 1);
|
||||
// the leftmost bit determines if this is an rpc or not
|
||||
// this leaves only 128 possible NetworkComponents per NetworkObject
|
||||
componentByte |= (byte)(isRpc ? 1 : 0);
|
||||
|
||||
return VelNetPlayer.SendMessage(this, componentByte, message, reliable);
|
||||
}
|
||||
|
||||
|
||||
public bool SendBytesToGroup(NetworkComponent component, bool isRpc, string group, byte[] message, bool reliable = true)
|
||||
{
|
||||
if (!IsMine)
|
||||
// only needs to be owner if this isn't an RPC
|
||||
// RPC calls can be called by non-owner
|
||||
if (!IsMine && !isRpc)
|
||||
{
|
||||
Debug.LogError("Can't send message if owner is null or not local", this);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// send the message and an identifier for which component it belongs to
|
||||
int index = syncedComponents.IndexOf(component);
|
||||
VelNetPlayer.SendGroupMessage(this, group, (byte)index, message, reliable);
|
||||
int componentIndex = syncedComponents.IndexOf(component);
|
||||
switch (componentIndex)
|
||||
{
|
||||
case > 127:
|
||||
Debug.LogError("Too many components.", component);
|
||||
return false;
|
||||
case < 0:
|
||||
Debug.LogError("WAAAAAAAH. NetworkObject doesn't have a reference to this component.", component);
|
||||
return false;
|
||||
}
|
||||
|
||||
public void ReceiveBytes(byte componentIdx, byte[] message)
|
||||
byte componentByte = (byte)(componentIndex << 1);
|
||||
componentByte |= (byte)(isRpc ? 1 : 0);
|
||||
|
||||
return VelNetPlayer.SendGroupMessage(this, group, componentByte, message, reliable);
|
||||
}
|
||||
|
||||
public void ReceiveBytes(byte componentIdx, bool isRpc, byte[] message)
|
||||
{
|
||||
// send the message to the right component
|
||||
try
|
||||
{
|
||||
if (isRpc)
|
||||
{
|
||||
syncedComponents[componentIdx].ReceiveRPC(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
syncedComponents[componentIdx].ReceiveBytes(message);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"Error in handling message:\n{e}", this);
|
||||
|
|
@ -123,13 +168,14 @@ namespace VelNet
|
|||
|
||||
if (GUILayout.Button("Find Network Components and add backreferences."))
|
||||
{
|
||||
NetworkComponent[] comps = t.GetComponents<NetworkComponent>();
|
||||
NetworkComponent[] comps = t.GetComponentsInChildren<NetworkComponent>();
|
||||
t.syncedComponents = comps.ToList();
|
||||
foreach (NetworkComponent c in comps)
|
||||
{
|
||||
c.networkObject = t;
|
||||
PrefabUtility.RecordPrefabInstancePropertyModifications(c);
|
||||
}
|
||||
|
||||
PrefabUtility.RecordPrefabInstancePropertyModifications(t);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
|
@ -33,6 +32,24 @@ namespace VelNet
|
|||
writer.Write(c.a);
|
||||
}
|
||||
|
||||
public static void Write(this BinaryWriter writer, List<int> l)
|
||||
{
|
||||
writer.Write(l.Count());
|
||||
foreach (int i in l)
|
||||
{
|
||||
writer.Write(i);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Write(this BinaryWriter writer, List<string> l)
|
||||
{
|
||||
writer.Write(l.Count());
|
||||
foreach (string i in l)
|
||||
{
|
||||
writer.Write(i);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Readers
|
||||
|
|
@ -62,6 +79,30 @@ namespace VelNet
|
|||
);
|
||||
}
|
||||
|
||||
public static List<int> ReadIntList(this BinaryReader reader)
|
||||
{
|
||||
int length = reader.ReadInt32();
|
||||
List<int> l = new List<int>(length);
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
l.Add(reader.ReadInt32());
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
public static List<string> ReadStringList(this BinaryReader reader)
|
||||
{
|
||||
int length = reader.ReadInt32();
|
||||
List<string> l = new List<string>(length);
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
l.Add(reader.ReadString());
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -139,5 +139,11 @@ namespace VelNet
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
[VelNetRPC]
|
||||
private void Test()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -11,6 +11,12 @@ using System.IO;
|
|||
|
||||
namespace VelNet
|
||||
{
|
||||
|
||||
/// <summary>Used to flag methods as remote-callable.</summary>
|
||||
public class VelNetRPC : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AddComponentMenu("VelNet/VelNet Manager")]
|
||||
public class VelNetManager : MonoBehaviour
|
||||
{
|
||||
|
|
@ -170,7 +176,7 @@ namespace VelNet
|
|||
public class RoomDataMessage : Message
|
||||
{
|
||||
public string room;
|
||||
public readonly List<Tuple<int, string>> members = new List<Tuple<int, string>>();
|
||||
public readonly List<(int, string)> members = new List<(int, string)>();
|
||||
}
|
||||
|
||||
public class JoinMessage : Message
|
||||
|
|
@ -354,7 +360,6 @@ namespace VelNet
|
|||
|
||||
try
|
||||
{
|
||||
Debug.Log(jm.room);
|
||||
OnJoinedRoom?.Invoke(jm.room);
|
||||
}
|
||||
// prevent errors in subscribers from breaking our code
|
||||
|
|
@ -495,6 +500,13 @@ namespace VelNet
|
|||
sceneObjects[i].networkId = -1 + "-" + sceneObjects[i].sceneNetworkId;
|
||||
sceneObjects[i].owner = masterPlayer;
|
||||
sceneObjects[i].isSceneObject = true; // needed for special handling when deleted
|
||||
try {
|
||||
sceneObjects[i].OwnershipChanged?.Invoke(masterPlayer);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError("Error in event handling.\n" + e);
|
||||
}
|
||||
|
||||
if (objects.ContainsKey(sceneObjects[i].networkId))
|
||||
{
|
||||
|
|
@ -681,7 +693,8 @@ namespace VelNet
|
|||
while (socketConnection.Connected)
|
||||
{
|
||||
//read a byte
|
||||
MessageReceivedType type = (MessageReceivedType)stream.ReadByte();
|
||||
int b = stream.ReadByte();
|
||||
MessageReceivedType type = (MessageReceivedType)b;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
|
|
@ -735,8 +748,7 @@ namespace VelNet
|
|||
int s = stream.ReadByte(); //size of string
|
||||
utf8data = ReadExact(stream, s); //the username
|
||||
string username = Encoding.UTF8.GetString(utf8data);
|
||||
rdm.members.Add(new Tuple<int, string>(client_id, username));
|
||||
Debug.Log(username);
|
||||
rdm.members.Add((client_id, username));
|
||||
}
|
||||
|
||||
AddMessage(rdm);
|
||||
|
|
@ -1042,7 +1054,7 @@ namespace VelNet
|
|||
SendToGroup(group, mem.ToArray(), reliable);
|
||||
}
|
||||
|
||||
internal static void SendToRoom(byte[] message, bool include_self = false, bool reliable = true, bool ordered = false)
|
||||
internal static bool SendToRoom(byte[] message, bool include_self = false, bool reliable = true, bool ordered = false)
|
||||
{
|
||||
byte sendType = (byte)MessageSendType.MESSAGE_OTHERS;
|
||||
if (include_self && ordered) sendType = (byte)MessageSendType.MESSAGE_ALL_ORDERED;
|
||||
|
|
@ -1057,7 +1069,7 @@ namespace VelNet
|
|||
writer.Write(sendType);
|
||||
writer.Write(get_be_bytes(message.Length));
|
||||
writer.Write(message);
|
||||
SendTcpMessage(mem.ToArray());
|
||||
return SendTcpMessage(mem.ToArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1066,11 +1078,12 @@ namespace VelNet
|
|||
Array.Copy(get_be_bytes(instance.userid), 0, toSend, 1, 4);
|
||||
Array.Copy(message, 0, toSend, 5, message.Length);
|
||||
SendUdpMessage(toSend, message.Length + 5); //shouldn't be over 1024...
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal static void SendToGroup(string group, byte[] message, bool reliable = true)
|
||||
internal static bool SendToGroup(string group, byte[] message, bool reliable = true)
|
||||
{
|
||||
byte[] utf8bytes = Encoding.UTF8.GetBytes(group);
|
||||
if (reliable)
|
||||
|
|
@ -1082,7 +1095,7 @@ namespace VelNet
|
|||
writer.Write(message);
|
||||
writer.Write((byte)utf8bytes.Length);
|
||||
writer.Write(utf8bytes);
|
||||
SendTcpMessage(stream.ToArray());
|
||||
return SendTcpMessage(stream.ToArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1093,6 +1106,7 @@ namespace VelNet
|
|||
Array.Copy(utf8bytes, 0, toSend, 6, utf8bytes.Length);
|
||||
Array.Copy(message, 0, toSend, 6 + utf8bytes.Length, message.Length);
|
||||
SendUdpMessage(toSend, 6 + utf8bytes.Length + message.Length);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1148,6 +1162,15 @@ namespace VelNet
|
|||
newObject.networkId = networkId;
|
||||
newObject.prefabName = prefabName;
|
||||
newObject.owner = localPlayer;
|
||||
try
|
||||
{
|
||||
newObject.OwnershipChanged?.Invoke(localPlayer);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError("Error in event handling.\n" + e);
|
||||
}
|
||||
|
||||
instance.objects.Add(newObject.networkId, newObject);
|
||||
|
||||
|
||||
|
|
@ -1170,6 +1193,14 @@ namespace VelNet
|
|||
newObject.networkId = networkId;
|
||||
newObject.prefabName = prefabName;
|
||||
newObject.owner = owner;
|
||||
try
|
||||
{
|
||||
newObject.OwnershipChanged?.Invoke(owner);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError("Error in event handling.\n" + e);
|
||||
}
|
||||
instance.objects.Add(newObject.networkId, newObject);
|
||||
}
|
||||
|
||||
|
|
@ -1230,6 +1261,12 @@ namespace VelNet
|
|||
/// <returns>True if successfully transferred, False if transfer message not sent</returns>
|
||||
public static bool TakeOwnership(string networkId)
|
||||
{
|
||||
if (!InRoom)
|
||||
{
|
||||
Debug.LogError("Can't take ownership. Not in a room.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// local player must exist
|
||||
if (LocalPlayer == null)
|
||||
{
|
||||
|
|
@ -1253,6 +1290,14 @@ namespace VelNet
|
|||
|
||||
// immediately successful
|
||||
instance.objects[networkId].owner = LocalPlayer;
|
||||
try
|
||||
{
|
||||
instance.objects[networkId].OwnershipChanged?.Invoke(LocalPlayer);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError("Error in event handling.\n" + e);
|
||||
}
|
||||
|
||||
// must be ordered, so that ownership transfers are not confused.
|
||||
// Also sent to all players, so that multiple simultaneous requests will result in the same outcome.
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace VelNet
|
|||
internal int lastObjectId;
|
||||
|
||||
|
||||
private bool isMaster;
|
||||
public bool IsMaster { get; private set; }
|
||||
|
||||
|
||||
public VelNetPlayer()
|
||||
|
|
@ -51,7 +51,7 @@ namespace VelNet
|
|||
}
|
||||
}
|
||||
|
||||
if (isMaster)
|
||||
if (IsMaster)
|
||||
{
|
||||
//send a list of scene object ids when someone joins
|
||||
SendSceneUpdate();
|
||||
|
|
@ -78,7 +78,9 @@ namespace VelNet
|
|||
|
||||
switch (messageType)
|
||||
{
|
||||
case VelNetManager.MessageType.ObjectSync: // sync update for an object I may own
|
||||
// sync update for an object "I" may own
|
||||
// "I" being the person sending
|
||||
case VelNetManager.MessageType.ObjectSync:
|
||||
{
|
||||
string objectKey = reader.ReadString();
|
||||
byte componentIdx = reader.ReadByte();
|
||||
|
|
@ -86,9 +88,13 @@ namespace VelNet
|
|||
byte[] syncMessage = reader.ReadBytes(messageLength);
|
||||
if (manager.objects.ContainsKey(objectKey))
|
||||
{
|
||||
if (manager.objects[objectKey].owner == this)
|
||||
bool isRpc = (componentIdx & 1) == 1;
|
||||
componentIdx = (byte)(componentIdx >> 1);
|
||||
|
||||
// rpcs can be sent by non-owners
|
||||
if (isRpc || manager.objects[objectKey].owner == this)
|
||||
{
|
||||
manager.objects[objectKey].ReceiveBytes(componentIdx, syncMessage);
|
||||
manager.objects[objectKey].ReceiveBytes(componentIdx, isRpc, syncMessage);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -101,6 +107,14 @@ namespace VelNet
|
|||
if (manager.objects.ContainsKey(networkId))
|
||||
{
|
||||
manager.objects[networkId].owner = this;
|
||||
try
|
||||
{
|
||||
manager.objects[networkId].OwnershipChanged?.Invoke(this);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError("Error in event handling.\n" + e);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
@ -130,9 +144,12 @@ namespace VelNet
|
|||
{
|
||||
VelNetManager.SomebodyDestroyedNetworkObject(reader.ReadString());
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case VelNetManager.MessageType.Custom: // custom packets
|
||||
// Custom packets. These are global data that can be sent from anywhere.
|
||||
// Any script can subscribe to the callback to receive the message data.
|
||||
case VelNetManager.MessageType.Custom:
|
||||
{
|
||||
int len = reader.ReadInt32();
|
||||
try
|
||||
|
|
@ -153,12 +170,12 @@ namespace VelNet
|
|||
|
||||
public void SetAsMasterPlayer()
|
||||
{
|
||||
isMaster = true;
|
||||
IsMaster = true;
|
||||
//if I'm master, I'm now responsible for updating all scene objects
|
||||
//FindObjectsOfType<NetworkObject>();
|
||||
}
|
||||
|
||||
public static void SendGroupMessage(NetworkObject obj, string group, byte componentIdx, byte[] data, bool reliable = true)
|
||||
public static bool SendGroupMessage(NetworkObject obj, string group, byte componentIdx, byte[] data, bool reliable = true)
|
||||
{
|
||||
using MemoryStream mem = new MemoryStream();
|
||||
using BinaryWriter writer = new BinaryWriter(mem);
|
||||
|
|
@ -167,10 +184,10 @@ namespace VelNet
|
|||
writer.Write(componentIdx);
|
||||
writer.Write(data.Length);
|
||||
writer.Write(data);
|
||||
VelNetManager.SendToGroup(group, mem.ToArray(), reliable);
|
||||
return VelNetManager.SendToGroup(group, mem.ToArray(), reliable);
|
||||
}
|
||||
|
||||
public static void SendMessage(NetworkObject obj, byte componentIdx, byte[] data, bool reliable = true)
|
||||
public static bool SendMessage(NetworkObject obj, byte componentIdx, byte[] data, bool reliable = true)
|
||||
{
|
||||
using MemoryStream mem = new MemoryStream();
|
||||
using BinaryWriter writer = new BinaryWriter(mem);
|
||||
|
|
@ -179,7 +196,7 @@ namespace VelNet
|
|||
writer.Write(componentIdx);
|
||||
writer.Write(data.Length);
|
||||
writer.Write(data);
|
||||
VelNetManager.SendToRoom(mem.ToArray(), false, reliable);
|
||||
return VelNetManager.SendToRoom(mem.ToArray(), false, reliable);
|
||||
}
|
||||
|
||||
public void SendSceneUpdate()
|
||||
|
|
@ -223,6 +240,14 @@ namespace VelNet
|
|||
|
||||
// immediately successful
|
||||
manager.objects[networkId].owner = this;
|
||||
try
|
||||
{
|
||||
manager.objects[networkId].OwnershipChanged?.Invoke(this);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError("Error in event handling.\n" + e);
|
||||
}
|
||||
|
||||
// must be ordered, so that ownership transfers are not confused.
|
||||
// Also sent to all players, so that multiple simultaneous requests will result in the same outcome.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "edu.uga.engr.vel.velnet",
|
||||
"displayName": "VelNet",
|
||||
"version": "1.0.12",
|
||||
"version": "1.0.13",
|
||||
"unity": "2019.1",
|
||||
"description": "A custom networking library for Unity.",
|
||||
"keywords": [
|
||||
|
|
|
|||
Loading…
Reference in New Issue