initial offline mode, added reference docs for message types

main
Anton Franzluebbers 2023-09-13 16:54:43 -04:00
parent fc3c866f1a
commit 98703f78ef
20 changed files with 531 additions and 255 deletions

1
.gitignore vendored
View File

@ -4,3 +4,4 @@ my.secrets
Documentation-old/
env/
Documentation/public/
node_modules/

5
Documentation/.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/Documentation.iml" filepath="$PROJECT_DIR$/.idea/Documentation.iml" />
</modules>
</component>
</project>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

View File

@ -0,0 +1,10 @@
There are several steps that need to happen before a client can join a room. Most of these can happen automatically using the default `VelNetManager` script.
## 1. Connecting
First, the TCP connection to the server must be established. If this step fails, offline mode is activated.
## 2. Logging in
Logging in registers this client with the server. The inputs for this are an app name and device id. `VelNetManager` automatically provides an appName that is appended with the version number if `onlyConnectToSameVersion` is true. The device id is generated from Unity's `SystemInfo.deviceUniqueIdentifier` and the app name to guarantee a different id per app and device.
## 3. Joining a room
Only after joining a room can normal networking take place between clients in that room. The client can send any string room name to join, and other clients that send the same string will be in that room with them.

View File

@ -0,0 +1,120 @@
VelNet uses a single-byte header on all messages that denotes the message type. The set of message types for sent messages is different from the set used when receiving messages.
It is generally not necessary to know or modify these internal data types.
!!! note
The server encodes ints with a Big-Endian format, but C# uses Little-Endian on almost all platforms. Use the `BinaryWriter.WriteBigEndian()` extensions to encode in Big-Endian on the C# side.
## MessageSentType
```cs
public enum MessageSendType
{
MESSAGE_OTHERS_ORDERED = 7,
MESSAGE_ALL_ORDERED = 8,
MESSAGE_LOGIN = 0,
MESSAGE_GETROOMS = 1,
MESSAGE_JOINROOM = 2,
MESSAGE_OTHERS = 3,
MESSAGE_ALL = 4,
MESSAGE_GROUP = 5,
MESSAGE_SETGROUP = 6,
MESSAGE_GETROOMDATA = 9
};
```
### MESSAGE_LOGIN = 0
This message contains:
- `byte` - The length of the deviceId string
- `byte[]` - UTF8 encoding of the deviceId string
- `byte` - The length of the appName string
- `byte[]` - UTF8 encoding of the appName string
### MESSAGE_GETROOMS = 1
This message contains no data, just the single-byte header.
### MESSAGE_JOINROOM = 2
This message contains:
- `byte` - The length of the roomName string
- `byte[]` - UTF8 encoding of the roomName string
### MESSAGE_OTHERS = 3
### MESSAGE_ALL = 4
### MESSAGE_GROUP = 5
### MESSAGE_SETGROUP = 6
### MESSAGE_OTHERS_ORDERED = 7
### MESSAGE_ALL_ORDERED = 8
### MESSAGE_GETROOMDATA = 9
## MessageReceivedType
```cs
public enum MessageReceivedType
{
LOGGED_IN = 0,
ROOM_LIST = 1,
PLAYER_JOINED = 2,
DATA_MESSAGE = 3,
MASTER_MESSAGE = 4,
YOU_JOINED = 5,
PLAYER_LEFT = 6,
YOU_LEFT = 7,
ROOM_DATA = 8
}
```
### LOGGED_IN = 0
This message contains:
- `int` - The userid given by the server to this user.
### ROOM_LIST = 1
This message contains:
- `int` - The length of the room mesesage string. This is an int instead of a byte because of the possible string length with many rooms.
- `byte[]` - A UTF8-encoded string for the room message
- This string is encoded as a comma-separated list of rooms, with the format `name:numUsers` for each room.
- e.g. `Common_1:0:3,Auditorium_123:0,room1:10`
### PLAYER_JOINED = 2
This message contains:
- `int` - The userid of the player that joined
- `byte` - The length of the room name string
- `byte[]` - A UTF8-encoded string for the room name
### DATA_MESSAGE = 3
This message contains:
- `int` - The userid of the player that sent this message
- `int` - The size of the payload
- `byte[]` - The message data
- Decoding the actual message data is handled in `VelNetPlayer.cs`
- Within DATA_MESSAGE messages, there is an additonal type header:
```cs
public enum MessageType : byte
{
ObjectSync,
TakeOwnership,
Instantiate,
InstantiateWithTransform,
Destroy,
DeleteSceneObjects,
Custom
}
```
### MASTER_MESSAGE = 4
This message contains:
- `int` - The new master client id. The sender of this message is the master.
### YOU_JOINED = 5
This is returned after you join a room.
This message contains:
- `int` - The number of players in the room
- For each player:
- `int` - The player's userid
- `byte` - The length of the room name string
- `byte[]` - A UTF8-encoded string for the room name
### PLAYER_LEFT = 6
This message contains:
- `int` - The player's userid
- `byte` - The length of the room name string
- `byte[]` - A UTF8-encoded string for the room name
### YOU_LEFT = 7
This message contains:
- `byte` - The length of the room name string
- `byte[]` - A UTF8-encoded string for the room name
### ROOM_DATA = 8
This message contains:
- `byte` - The length of the room name string
- `byte[]` - A UTF8-encoded string for the room name
- `int` - The number of client data blocks to read
- For each client data block:
- `int` - The userid of this client
- `byte` - The length of the username string
- `byte[]` - A UTF8-encoded string for the username

View File

@ -0,0 +1,5 @@
VelNet supports an offline mode that lets you write client code in the same way even in a situation where there is no internet or no server available.
Offline mode is activated automatically if no initial TCP connection can be established by `VelNetManager.cs`
Messages are intercepted by VelNetManager and send to a "FakeServer" function instead of to the server, and realistic response messages are constructed and sent to the callback functions.

View File

@ -2,7 +2,7 @@ site_name: VelNet Docs
site_url: https://docs.velnet.ugavel.com
repo_url: https://github.com/velaboratory/VelNetUnity
repo_name: velaboratory/VelNetUnity
edit_uri: edit/main/Documentation
edit_uri: edit/main/Documentation/docs
theme:
name: material

View File

@ -5,7 +5,7 @@ using UnityEngine;
namespace VelNet
{
public static class BinaryWriterExtensions
public static partial class BinaryWriterExtensions
{
#region Writers

View File

@ -8,6 +8,7 @@ using UnityEngine;
using System.Net;
using UnityEngine.SceneManagement;
using System.IO;
using System.Threading.Tasks;
namespace VelNet
{
@ -119,6 +120,8 @@ namespace VelNet
public bool connected;
private bool wasConnected;
private double lastConnectionCheck;
private bool offlineMode;
private string offlineRoomName;
public List<NetworkObject> prefabs = new List<NetworkObject>();
public NetworkObject[] sceneObjects;
@ -316,7 +319,8 @@ namespace VelNet
onlyConnectToSameVersion
? $"{Application.productName}_{Application.version}"
: $"{Application.productName}",
Hash128.Compute(SystemInfo.deviceUniqueIdentifier).ToString()
Hash128.Compute(SystemInfo.deviceUniqueIdentifier + Application.productName)
.ToString()
);
}
@ -742,137 +746,7 @@ namespace VelNet
AddMessage(new ConnectedMessage());
while (socketConnection.Connected)
{
//read a byte
int b = stream.ReadByte();
MessageReceivedType type = (MessageReceivedType)b;
switch (type)
{
//login
case MessageReceivedType.LOGGED_IN:
{
AddMessage(new LoginMessage
{
// not really the sender...
userId = GetIntFromBytes(ReadExact(stream, 4))
});
break;
}
//rooms
case MessageReceivedType.ROOM_LIST:
{
RoomsMessage m = new RoomsMessage();
m.rooms = new List<ListedRoom>();
int N = GetIntFromBytes(ReadExact(stream, 4)); //the size of the payload
byte[] utf8data = ReadExact(stream, N);
string roomMessage = Encoding.UTF8.GetString(utf8data);
string[] sections = roomMessage.Split(',');
foreach (string s in sections)
{
string[] pieces = s.Split(':');
if (pieces.Length == 2)
{
m.rooms.Add(new ListedRoom
{
name = pieces[0],
numUsers = int.Parse(pieces[1])
});
}
}
AddMessage(m);
break;
}
case MessageReceivedType.ROOM_DATA:
{
RoomDataMessage rdm = new RoomDataMessage();
int N = stream.ReadByte();
byte[] utf8data = ReadExact(stream, N); //the room name, encoded as utf-8
string roomname = Encoding.UTF8.GetString(utf8data);
N = GetIntFromBytes(ReadExact(stream, 4)); //the number of client datas to read
rdm.room = roomname;
for (int i = 0; i < N; i++)
{
// client id + short string
int client_id = GetIntFromBytes(ReadExact(stream, 4));
int s = stream.ReadByte(); //size of string
utf8data = ReadExact(stream, s); //the username
string username = Encoding.UTF8.GetString(utf8data);
rdm.members.Add((client_id, username));
}
AddMessage(rdm);
break;
}
//joined
case MessageReceivedType.PLAYER_JOINED:
{
JoinMessage m = new JoinMessage();
m.userId = GetIntFromBytes(ReadExact(stream, 4));
int N = stream.ReadByte();
byte[] utf8data = ReadExact(stream, N); //the room name, encoded as utf-8
m.room = Encoding.UTF8.GetString(utf8data);
AddMessage(m);
break;
}
//data
case MessageReceivedType.DATA_MESSAGE:
{
DataMessage m = new DataMessage();
m.senderId = GetIntFromBytes(ReadExact(stream, 4));
int N = GetIntFromBytes(ReadExact(stream, 4)); //the size of the payload
m.data = ReadExact(stream, N); //the message
AddMessage(m);
break;
}
// new master
case MessageReceivedType.MASTER_MESSAGE:
{
ChangeMasterMessage m = new ChangeMasterMessage();
m.masterId = GetIntFromBytes(ReadExact(stream, 4)); // sender is the new master
AddMessage(m);
break;
}
case MessageReceivedType.YOU_JOINED:
{
YouJoinedMessage m = new YouJoinedMessage();
int N = GetIntFromBytes(ReadExact(stream, 4));
m.playerIds = new List<int>();
for (int i = 0; i < N; i++)
{
m.playerIds.Add(GetIntFromBytes(ReadExact(stream, 4)));
}
N = stream.ReadByte();
byte[] utf8data = ReadExact(stream, N); //the room name, encoded as utf-8
m.room = Encoding.UTF8.GetString(utf8data);
AddMessage(m);
break;
}
case MessageReceivedType.PLAYER_LEFT:
{
PlayerLeftMessage m = new PlayerLeftMessage();
m.userId = GetIntFromBytes(ReadExact(stream, 4));
int N = stream.ReadByte();
byte[] utf8data = ReadExact(stream, N); //the room name, encoded as utf-8
m.room = Encoding.UTF8.GetString(utf8data);
AddMessage(m);
break;
}
case MessageReceivedType.YOU_LEFT:
{
YouLeftMessage m = new YouLeftMessage();
int N = stream.ReadByte();
byte[] utf8data = ReadExact(stream, N); //the room name, encoded as utf-8
m.room = Encoding.UTF8.GetString(utf8data);
AddMessage(m);
break;
}
}
HandleIncomingMessage(reader);
}
}
catch (ThreadAbortException)
@ -882,6 +756,9 @@ namespace VelNet
catch (SocketException socketException)
{
VelNetLogger.Error("Socket exception: " + socketException);
VelNetLogger.Error("Switching to offline mode");
offlineMode = true;
AddMessage(new ConnectedMessage());
}
catch (Exception ex)
{
@ -891,8 +768,145 @@ namespace VelNet
connected = false;
}
private void HandleIncomingMessage(BinaryReader reader)
{
MessageReceivedType type = (MessageReceivedType)reader.ReadByte();
Debug.Log(type);
switch (type)
{
//login
case MessageReceivedType.LOGGED_IN:
{
AddMessage(new LoginMessage
{
// not really the sender...
userId = GetIntFromBytes(reader.ReadBytes(4))
});
break;
}
//rooms
case MessageReceivedType.ROOM_LIST:
{
RoomsMessage m = new RoomsMessage();
m.rooms = new List<ListedRoom>();
int N = GetIntFromBytes(reader.ReadBytes(4)); //the size of the payload
byte[] utf8data = reader.ReadBytes(N);
string roomMessage = Encoding.UTF8.GetString(utf8data);
string[] sections = roomMessage.Split(',');
foreach (string s in sections)
{
string[] pieces = s.Split(':');
if (pieces.Length == 2)
{
m.rooms.Add(new ListedRoom
{
name = pieces[0],
numUsers = int.Parse(pieces[1])
});
}
}
AddMessage(m);
break;
}
case MessageReceivedType.ROOM_DATA:
{
RoomDataMessage rdm = new RoomDataMessage();
int N = reader.ReadByte();
byte[] utf8data = reader.ReadBytes(N); //the room name, encoded as utf-8
string roomname = Encoding.UTF8.GetString(utf8data);
N = GetIntFromBytes(reader.ReadBytes(4)); //the number of client datas to read
rdm.room = roomname;
for (int i = 0; i < N; i++)
{
// client id + short string
int clientId = GetIntFromBytes(reader.ReadBytes(4));
int s = reader.ReadByte(); //size of string
utf8data = reader.ReadBytes(s); //the username
string username = Encoding.UTF8.GetString(utf8data);
rdm.members.Add((clientId, username));
}
AddMessage(rdm);
break;
}
//joined
case MessageReceivedType.PLAYER_JOINED:
{
JoinMessage m = new JoinMessage();
m.userId = GetIntFromBytes(reader.ReadBytes(4));
int N = reader.ReadByte();
byte[] utf8data = reader.ReadBytes(N); //the room name, encoded as utf-8
m.room = Encoding.UTF8.GetString(utf8data);
AddMessage(m);
break;
}
//data
case MessageReceivedType.DATA_MESSAGE:
{
DataMessage m = new DataMessage();
m.senderId = GetIntFromBytes(reader.ReadBytes(4));
int N = GetIntFromBytes(reader.ReadBytes(4)); //the size of the payload
m.data = reader.ReadBytes(N); //the message
AddMessage(m);
break;
}
// new master
case MessageReceivedType.MASTER_MESSAGE:
{
ChangeMasterMessage m = new ChangeMasterMessage();
m.masterId = GetIntFromBytes(reader.ReadBytes(4)); // sender is the new master
AddMessage(m);
break;
}
case MessageReceivedType.YOU_JOINED:
{
YouJoinedMessage m = new YouJoinedMessage();
int N = GetIntFromBytes(reader.ReadBytes(4));
m.playerIds = new List<int>();
for (int i = 0; i < N; i++)
{
m.playerIds.Add(GetIntFromBytes(reader.ReadBytes(4)));
}
N = reader.ReadByte();
byte[] utf8data = reader.ReadBytes(N); //the room name, encoded as utf-8
m.room = Encoding.UTF8.GetString(utf8data);
AddMessage(m);
break;
}
case MessageReceivedType.PLAYER_LEFT:
{
PlayerLeftMessage m = new PlayerLeftMessage();
m.userId = GetIntFromBytes(reader.ReadBytes(4));
int N = reader.ReadByte();
byte[] utf8data = reader.ReadBytes(N); //the room name, encoded as utf-8
m.room = Encoding.UTF8.GetString(utf8data);
AddMessage(m);
break;
}
case MessageReceivedType.YOU_LEFT:
{
YouLeftMessage m = new YouLeftMessage();
int N = reader.ReadByte();
byte[] utf8data = reader.ReadBytes(N); //the room name, encoded as utf-8
m.room = Encoding.UTF8.GetString(utf8data);
AddMessage(m);
break;
}
default:
VelNetLogger.Error("Unknown message type");
throw new ArgumentOutOfRangeException(nameof(type), type, null);
}
}
private void ListenForDataUDP()
{
if (offlineMode) return;
//I don't yet have a UDP connection
try
{
@ -900,17 +914,14 @@ namespace VelNet
Debug.Assert(addresses.Length > 0);
RemoteEndPoint = new IPEndPoint(addresses[0], port);
udpSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);
udpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
udpConnected = false;
byte[] buffer = new byte[1024];
while (true)
{
buffer[0] = 0;
Array.Copy(get_be_bytes(userid), 0, buffer, 1, 4);
Array.Copy(GetBigEndianBytes(userid), 0, buffer, 1, 4);
udpSocket.SendTo(buffer, 5, SocketFlags.None, RemoteEndPoint);
if (udpSocket.Available == 0)
@ -981,6 +992,12 @@ namespace VelNet
/// <returns>True if the message successfully sent. False if it failed and we should quit</returns>
private static bool SendTcpMessage(byte[] message)
{
if (instance.offlineMode)
{
instance.FakeServer(message);
return true;
}
// Logging.Info("Sent: " + clientMessage);
if (instance.socketConnection == null)
{
@ -1019,7 +1036,7 @@ namespace VelNet
return true;
}
private static byte[] get_be_bytes(int n)
private static byte[] GetBigEndianBytes(int n)
{
return BitConverter.GetBytes(n).Reverse().ToArray();
}
@ -1104,10 +1121,10 @@ namespace VelNet
MemoryStream stream = new MemoryStream();
BinaryWriter writer = new BinaryWriter(stream);
byte[] R = Encoding.UTF8.GetBytes(roomName);
byte[] roomBytes = Encoding.UTF8.GetBytes(roomName);
writer.Write((byte)MessageSendType.MESSAGE_JOINROOM);
writer.Write((byte)R.Length);
writer.Write(R);
writer.Write((byte)roomBytes.Length);
writer.Write(roomBytes);
SendTcpMessage(stream.ToArray());
}
@ -1168,7 +1185,7 @@ namespace VelNet
MemoryStream mem = new MemoryStream();
BinaryWriter writer = new BinaryWriter(mem);
writer.Write(sendType);
writer.Write(get_be_bytes(message.Length));
writer.WriteBigEndian(message.Length);
writer.Write(message);
return SendTcpMessage(mem.ToArray());
}
@ -1176,7 +1193,7 @@ namespace VelNet
{
//udp message needs the type
toSend[0] = sendType; //we don't
Array.Copy(get_be_bytes(instance.userid), 0, toSend, 1, 4);
Array.Copy(GetBigEndianBytes(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;
@ -1192,7 +1209,7 @@ namespace VelNet
MemoryStream stream = new MemoryStream();
BinaryWriter writer = new BinaryWriter(stream);
writer.Write((byte)MessageSendType.MESSAGE_GROUP);
writer.Write(get_be_bytes(message.Length));
writer.WriteBigEndian(message.Length);
writer.Write(message);
writer.Write((byte)utf8bytes.Length);
writer.Write(utf8bytes);
@ -1201,7 +1218,7 @@ namespace VelNet
else
{
toSend[0] = (byte)MessageSendType.MESSAGE_GROUP;
Array.Copy(get_be_bytes(instance.userid), 0, toSend, 1, 4);
Array.Copy(GetBigEndianBytes(instance.userid), 0, toSend, 1, 4);
//also need to send the group
toSend[5] = (byte)utf8bytes.Length;
Array.Copy(utf8bytes, 0, toSend, 6, utf8bytes.Length);
@ -1223,14 +1240,14 @@ namespace VelNet
MemoryStream stream = new MemoryStream();
BinaryWriter writer = new BinaryWriter(stream);
byte[] R = Encoding.UTF8.GetBytes(groupName);
byte[] groupNameBytes = Encoding.UTF8.GetBytes(groupName);
writer.Write((byte)6);
writer.Write((byte)R.Length);
writer.Write(R);
writer.Write(get_be_bytes(clientIds.Count * 4));
writer.Write((byte)groupNameBytes.Length);
writer.Write(groupNameBytes);
writer.WriteBigEndian(clientIds.Count * 4);
foreach (int c in clientIds)
{
writer.Write(get_be_bytes(c));
writer.WriteBigEndian(c);
}
SendTcpMessage(stream.ToArray());
@ -1490,5 +1507,100 @@ namespace VelNet
return true;
}
/// <summary>
/// Pretends to be the server and sends back the result to be handled. Only should be called in offline mode.
/// </summary>
/// <param name="message">The message that was meant to be sent to the server.</param>
private void FakeServer(byte[] message)
{
MemoryStream mem = new MemoryStream(message);
BinaryReader reader = new BinaryReader(mem);
MessageSendType messageType = (MessageSendType)reader.ReadByte();
MemoryStream outMem = new MemoryStream();
BinaryWriter outWriter = new BinaryWriter(outMem);
switch (messageType)
{
case MessageSendType.MESSAGE_OTHERS_ORDERED:
break;
case MessageSendType.MESSAGE_ALL_ORDERED:
break;
case MessageSendType.MESSAGE_LOGIN:
outWriter.Write((byte)MessageReceivedType.LOGGED_IN);
outWriter.WriteBigEndian(0);
break;
case MessageSendType.MESSAGE_GETROOMS:
outWriter.Write((byte)MessageReceivedType.ROOM_LIST);
outWriter.WriteBigEndian(0);
break;
case MessageSendType.MESSAGE_JOINROOM:
{
string roomName = Encoding.UTF8.GetString(reader.ReadBytes(reader.ReadByte()));
// if leaving a room
if (string.IsNullOrEmpty(roomName))
{
outWriter.Write((byte)MessageReceivedType.YOU_LEFT);
byte[] roomNameBytes = Encoding.UTF8.GetBytes(offlineRoomName);
outWriter.Write((byte)roomNameBytes.Length);
outWriter.Write(roomNameBytes);
}
else
{
outWriter.Write((byte)MessageReceivedType.YOU_JOINED);
outWriter.WriteBigEndian(1); // num players
outWriter.WriteBigEndian(0); // our userid
byte[] roomNameBytes = Encoding.UTF8.GetBytes(roomName);
outWriter.Write((byte)roomNameBytes.Length);
outWriter.Write(roomNameBytes);
}
offlineRoomName = roomName;
break;
}
case MessageSendType.MESSAGE_OTHERS:
break;
case MessageSendType.MESSAGE_ALL:
break;
case MessageSendType.MESSAGE_GROUP:
break;
case MessageSendType.MESSAGE_SETGROUP:
break;
case MessageSendType.MESSAGE_GETROOMDATA:
{
outWriter.Write((byte)MessageReceivedType.ROOM_DATA);
byte[] roomNameBytes = Encoding.UTF8.GetBytes("OFFLINE");
outWriter.Write((byte)roomNameBytes.Length);
outWriter.Write(roomNameBytes);
outWriter.WriteBigEndian(0);
break;
}
default:
throw new ArgumentOutOfRangeException();
}
outMem.Position = 0;
// if we run this in the same thread, then it is modifying the messages collection while iterating
Task.Run(() => { HandleIncomingMessage(new BinaryReader(outMem)); });
}
}
public static partial class BinaryWriterExtensions
{
public static void WriteBigEndian(this BinaryWriter writer, int value)
{
byte[] data = BitConverter.GetBytes(value);
Array.Reverse(data);
writer.Write(data);
}
public static int ReadBigEndian(this BinaryReader reader)
{
byte[] data = reader.ReadBytes(4);
Array.Reverse(data);
return BitConverter.ToInt32(data, 0);
}
}
}

View File

@ -1,6 +1,7 @@
using System.Collections.Generic;
using System;
using System.IO;
using System.Text;
using UnityEngine;
namespace VelNet
@ -82,12 +83,11 @@ namespace VelNet
///
/// The length of the byte[] for message is fixed according to the message type
/// </summary>
public void HandleMessage(VelNetManager.DataMessage m, bool unknown_sender = false)
public void HandleMessage(VelNetManager.DataMessage m, bool unknownSender = false)
{
using MemoryStream mem = new MemoryStream(m.data);
using BinaryReader reader = new BinaryReader(mem);
//individual message parameters separated by comma
VelNetManager.MessageType messageType = (VelNetManager.MessageType)reader.ReadByte();
if (messageType == VelNetManager.MessageType.Custom)
@ -109,7 +109,7 @@ namespace VelNet
return;
}
if (unknown_sender)
if (unknownSender)
{
VelNetLogger.Error("Received non-custom message from player that doesn't exist ");
return;

View File

@ -104,7 +104,7 @@ NavMeshSettings:
serializedVersion: 2
m_ObjectHideFlags: 0
m_BuildSettings:
serializedVersion: 2
serializedVersion: 3
agentTypeID: 0
agentRadius: 0.5
agentHeight: 2
@ -117,7 +117,7 @@ NavMeshSettings:
cellSize: 0.16666667
manualTileSize: 0
tileSize: 256
accuratePlacement: 0
buildHeightMesh: 0
maxJobWorkers: 0
preserveTilesOutsideBounds: 0
debug:
@ -199,7 +199,9 @@ Canvas:
m_OverrideSorting: 0
m_OverridePixelPerfect: 0
m_SortingBucketNormalizedSize: 0
m_VertexColorAlwaysGammaSpace: 0
m_AdditionalShaderChannelsFlag: 0
m_UpdateRectTransformForStandalone: 0
m_SortingLayerID: 0
m_SortingOrder: 0
m_TargetDisplay: 0
@ -337,6 +339,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3}
m_Name:
m_EditorClassIdentifier:
m_SendPointerHoverToParent: 1
m_HorizontalAxis: Horizontal
m_VerticalAxis: Vertical
m_SubmitButton: Submit
@ -372,7 +375,7 @@ Transform:
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &652307109
GameObject:
@ -466,7 +469,7 @@ Transform:
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 2
m_RootOrder: 3
m_LocalEulerAnglesHint: {x: 25.729, y: -12.365, z: 17.037}
--- !u!1 &903768653
GameObject:
@ -500,9 +503,17 @@ Camera:
m_projectionMatrixMode: 1
m_GateFitMode: 2
m_FOVAxisMode: 0
m_Iso: 200
m_ShutterSpeed: 0.005
m_Aperture: 16
m_FocusDistance: 10
m_FocalLength: 50
m_BladeCount: 5
m_Curvature: {x: 2, y: 11}
m_BarrelClipping: 0.25
m_Anamorphism: 0
m_SensorSize: {x: 36, y: 24}
m_LensShift: {x: 0, y: 0}
m_FocalLength: 50
m_NormalizedViewPortRect:
serializedVersion: 2
x: 0
@ -542,7 +553,7 @@ Transform:
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 1
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!81 &903768658
AudioListener:
@ -583,7 +594,7 @@ Transform:
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 3
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1099803616
MonoBehaviour:
@ -597,7 +608,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 233344de094f11341bdb834d564708dc, type: 3}
m_Name:
m_EditorClassIdentifier:
host: vn.ugavel.com
host: velnet-demo.ugavel.com
port: 5000
udpConnected: 0
userid: -1

View File

@ -104,7 +104,7 @@ NavMeshSettings:
serializedVersion: 2
m_ObjectHideFlags: 0
m_BuildSettings:
serializedVersion: 2
serializedVersion: 3
agentTypeID: 0
agentRadius: 0.5
agentHeight: 2
@ -117,7 +117,7 @@ NavMeshSettings:
cellSize: 0.16666667
manualTileSize: 0
tileSize: 256
accuratePlacement: 0
buildHeightMesh: 0
maxJobWorkers: 0
preserveTilesOutsideBounds: 0
debug:
@ -585,7 +585,9 @@ Canvas:
m_OverrideSorting: 0
m_OverridePixelPerfect: 0
m_SortingBucketNormalizedSize: 0
m_VertexColorAlwaysGammaSpace: 0
m_AdditionalShaderChannelsFlag: 0
m_UpdateRectTransformForStandalone: 0
m_SortingLayerID: 0
m_SortingOrder: 0
m_TargetDisplay: 0
@ -749,6 +751,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3}
m_Name:
m_EditorClassIdentifier:
m_SendPointerHoverToParent: 1
m_HorizontalAxis: Horizontal
m_VerticalAxis: Vertical
m_SubmitButton: Submit
@ -1733,9 +1736,17 @@ Camera:
m_projectionMatrixMode: 1
m_GateFitMode: 2
m_FOVAxisMode: 0
m_Iso: 200
m_ShutterSpeed: 0.005
m_Aperture: 16
m_FocusDistance: 10
m_FocalLength: 50
m_BladeCount: 5
m_Curvature: {x: 2, y: 11}
m_BarrelClipping: 0.25
m_Anamorphism: 0
m_SensorSize: {x: 36, y: 24}
m_LensShift: {x: 0, y: 0}
m_FocalLength: 50
m_NormalizedViewPortRect:
serializedVersion: 2
x: 0
@ -2055,7 +2066,7 @@ MonoBehaviour:
prefabName:
isSceneObject: 1
syncedComponents:
- {fileID: 948755939}
- {fileID: 0}
--- !u!114 &948755941
MonoBehaviour:
m_ObjectHideFlags: 0
@ -2518,7 +2529,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 233344de094f11341bdb834d564708dc, type: 3}
m_Name:
m_EditorClassIdentifier:
host: vn.ugavel.com
host: velnet-demo.ugavel.com
port: 5000
udpConnected: 0
userid: -1
@ -4106,7 +4117,7 @@ MonoBehaviour:
prefabName:
isSceneObject: 1
syncedComponents:
- {fileID: 2021764945}
- {fileID: 0}
--- !u!114 &2021764945
MonoBehaviour:
m_ObjectHideFlags: 0
@ -4372,6 +4383,7 @@ PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 0}
m_Modifications:
- target: {fileID: 3951900052977689805, guid: 6e4a023f70e01405e8b249a4488fe319, type: 3}
@ -4439,4 +4451,7 @@ PrefabInstance:
value: 0
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 6e4a023f70e01405e8b249a4488fe319, type: 3}

View File

@ -104,7 +104,7 @@ NavMeshSettings:
serializedVersion: 2
m_ObjectHideFlags: 0
m_BuildSettings:
serializedVersion: 2
serializedVersion: 3
agentTypeID: 0
agentRadius: 0.5
agentHeight: 2
@ -117,7 +117,7 @@ NavMeshSettings:
cellSize: 0.16666667
manualTileSize: 0
tileSize: 256
accuratePlacement: 0
buildHeightMesh: 0
maxJobWorkers: 0
preserveTilesOutsideBounds: 0
debug:
@ -152,7 +152,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 233344de094f11341bdb834d564708dc, type: 3}
m_Name:
m_EditorClassIdentifier:
host: vn.ugavel.com
host: velnet-demo.ugavel.com
port: 5000
udpConnected: 0
userid: -1
@ -301,9 +301,17 @@ BoxCollider:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 958953873}
m_Material: {fileID: 0}
m_IncludeLayers:
serializedVersion: 2
m_Bits: 0
m_ExcludeLayers:
serializedVersion: 2
m_Bits: 0
m_LayerOverridePriority: 0
m_IsTrigger: 0
m_ProvidesContacts: 0
m_Enabled: 1
serializedVersion: 2
serializedVersion: 3
m_Size: {x: 1, y: 1, z: 1}
m_Center: {x: 0, y: 0, z: 0}
--- !u!23 &958953875
@ -386,6 +394,9 @@ MonoBehaviour:
networkObject: {fileID: 958953879}
serializationRateHz: 30
hybridOnChangeCompression: 1
position: 1
rotation: 1
scale: 0
useLocalTransform: 0
teleportDistance: 0
teleportAngle: 0
@ -448,9 +459,17 @@ Camera:
m_projectionMatrixMode: 1
m_GateFitMode: 2
m_FOVAxisMode: 0
m_Iso: 200
m_ShutterSpeed: 0.005
m_Aperture: 16
m_FocusDistance: 10
m_FocalLength: 50
m_BladeCount: 5
m_Curvature: {x: 2, y: 11}
m_BarrelClipping: 0.25
m_Anamorphism: 0
m_SensorSize: {x: 36, y: 24}
m_LensShift: {x: 0, y: 0}
m_FocalLength: 50
m_NormalizedViewPortRect:
serializedVersion: 2
x: 0

View File

@ -616,7 +616,7 @@ RectTransform:
- {fileID: 1020014860}
- {fileID: 1536292193}
m_Father: {fileID: 0}
m_RootOrder: 1
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
@ -788,7 +788,7 @@ Transform:
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &498776799
GameObject:
@ -1319,7 +1319,7 @@ Transform:
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 2
m_RootOrder: 3
m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0}
--- !u!1 &711524766
GameObject:
@ -1779,7 +1779,7 @@ Transform:
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 3
m_RootOrder: 4
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!81 &903768658
AudioListener:
@ -2237,7 +2237,7 @@ Transform:
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 5
m_RootOrder: 6
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1020014859
GameObject:
@ -2585,7 +2585,7 @@ Transform:
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 6
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1099803616
MonoBehaviour:
@ -2599,7 +2599,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 233344de094f11341bdb834d564708dc, type: 3}
m_Name:
m_EditorClassIdentifier:
host: velnet-demo.ugavel.com
host: velnet-demo2.ugavel.com
port: 5000
udpConnected: 0
userid: -1
@ -3251,7 +3251,7 @@ Transform:
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 4
m_RootOrder: 5
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1536292192
GameObject:

View File

@ -104,7 +104,7 @@ NavMeshSettings:
serializedVersion: 2
m_ObjectHideFlags: 0
m_BuildSettings:
serializedVersion: 2
serializedVersion: 3
agentTypeID: 0
agentRadius: 0.5
agentHeight: 2
@ -117,7 +117,7 @@ NavMeshSettings:
cellSize: 0.16666667
manualTileSize: 0
tileSize: 256
accuratePlacement: 0
buildHeightMesh: 0
maxJobWorkers: 0
preserveTilesOutsideBounds: 0
debug:
@ -280,7 +280,9 @@ Canvas:
m_OverrideSorting: 0
m_OverridePixelPerfect: 0
m_SortingBucketNormalizedSize: 0
m_VertexColorAlwaysGammaSpace: 0
m_AdditionalShaderChannelsFlag: 0
m_UpdateRectTransformForStandalone: 0
m_SortingLayerID: 0
m_SortingOrder: 0
m_TargetDisplay: 0
@ -517,6 +519,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3}
m_Name:
m_EditorClassIdentifier:
m_SendPointerHoverToParent: 1
m_HorizontalAxis: Horizontal
m_VerticalAxis: Vertical
m_SubmitButton: Submit
@ -552,7 +555,7 @@ Transform:
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &513088493
GameObject:
@ -722,7 +725,7 @@ Transform:
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 2
m_RootOrder: 3
m_LocalEulerAnglesHint: {x: 25.729, y: -12.365, z: 17.037}
--- !u!1 &686695937
GameObject:
@ -987,9 +990,17 @@ Camera:
m_projectionMatrixMode: 1
m_GateFitMode: 2
m_FOVAxisMode: 0
m_Iso: 200
m_ShutterSpeed: 0.005
m_Aperture: 16
m_FocusDistance: 10
m_FocalLength: 50
m_BladeCount: 5
m_Curvature: {x: 2, y: 11}
m_BarrelClipping: 0.25
m_Anamorphism: 0
m_SensorSize: {x: 36, y: 24}
m_LensShift: {x: 0, y: 0}
m_FocalLength: 50
m_NormalizedViewPortRect:
serializedVersion: 2
x: 0
@ -1029,7 +1040,7 @@ Transform:
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 1
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!81 &903768658
AudioListener:
@ -1305,7 +1316,7 @@ Transform:
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 3
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1099803616
MonoBehaviour:
@ -1319,7 +1330,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 233344de094f11341bdb834d564708dc, type: 3}
m_Name:
m_EditorClassIdentifier:
host: vn.ugavel.com
host: velnet-demo.ugavel.com
port: 5000
udpConnected: 0
userid: -1

View File

@ -1,7 +1,7 @@
{
"name": "edu.uga.engr.vel.velnet",
"displayName": "VelNet",
"version": "1.2.3",
"version": "1.3.0",
"unity": "2019.1",
"description": "A custom networking library for Unity.",
"keywords": [

View File

@ -1,14 +1,10 @@
{
"dependencies": {
"com.franzco.unityutilities": "https://github.com/AntonFranzluebbers/unityutilities.git",
"com.unity.ai.navigation": "1.1.3",
"com.unity.collab-proxy": "2.0.4",
"com.unity.ide.rider": "3.0.21",
"com.unity.ide.visualstudio": "2.0.18",
"com.unity.ide.rider": "3.0.25",
"com.unity.ide.visualstudio": "2.0.21",
"com.unity.ide.vscode": "1.2.5",
"com.unity.test-framework": "1.3.2",
"com.unity.textmeshpro": "3.0.6",
"com.unity.timeline": "1.7.4",
"com.unity.toolchain.win-x86_64-linux-x86_64": "2.0.6",
"com.unity.ugui": "1.0.0",
"com.unity.modules.ai": "1.0.0",

View File

@ -1,31 +1,5 @@
{
"dependencies": {
"com.franzco.unityutilities": {
"version": "https://github.com/AntonFranzluebbers/unityutilities.git",
"depth": 0,
"source": "git",
"dependencies": {
"com.unity.nuget.newtonsoft-json": "2.0.0-preview",
"com.unity.xr.legacyinputhelpers": "2.1.7"
},
"hash": "330ff73d80febbf9b505dd0ebd86d370d12fc73d"
},
"com.unity.ai.navigation": {
"version": "1.1.3",
"depth": 0,
"source": "registry",
"dependencies": {
"com.unity.modules.ai": "1.0.0"
},
"url": "https://packages.unity.com"
},
"com.unity.collab-proxy": {
"version": "2.0.4",
"depth": 0,
"source": "registry",
"dependencies": {},
"url": "https://packages.unity.com"
},
"com.unity.ext.nunit": {
"version": "2.0.3",
"depth": 1,
@ -34,7 +8,7 @@
"url": "https://packages.unity.com"
},
"com.unity.ide.rider": {
"version": "3.0.21",
"version": "3.0.25",
"depth": 0,
"source": "registry",
"dependencies": {
@ -43,7 +17,7 @@
"url": "https://packages.unity.com"
},
"com.unity.ide.visualstudio": {
"version": "2.0.18",
"version": "2.0.21",
"depth": 0,
"source": "registry",
"dependencies": {
@ -58,13 +32,6 @@
"dependencies": {},
"url": "https://packages.unity.com"
},
"com.unity.nuget.newtonsoft-json": {
"version": "3.2.1",
"depth": 1,
"source": "registry",
"dependencies": {},
"url": "https://packages.unity.com"
},
"com.unity.sysroot": {
"version": "2.0.7",
"depth": 1,
@ -101,18 +68,6 @@
},
"url": "https://packages.unity.com"
},
"com.unity.timeline": {
"version": "1.7.4",
"depth": 0,
"source": "registry",
"dependencies": {
"com.unity.modules.director": "1.0.0",
"com.unity.modules.animation": "1.0.0",
"com.unity.modules.audio": "1.0.0",
"com.unity.modules.particlesystem": "1.0.0"
},
"url": "https://packages.unity.com"
},
"com.unity.toolchain.win-x86_64-linux-x86_64": {
"version": "2.0.6",
"depth": 0,
@ -132,16 +87,6 @@
"com.unity.modules.imgui": "1.0.0"
}
},
"com.unity.xr.legacyinputhelpers": {
"version": "2.1.10",
"depth": 1,
"source": "registry",
"dependencies": {
"com.unity.modules.vr": "1.0.0",
"com.unity.modules.xr": "1.0.0"
},
"url": "https://packages.unity.com"
},
"edu.uga.engr.vel.velnet": {
"version": "file:VelNetUnity",
"depth": 0,