This commit is contained in:
2023-11-28 11:41:03 +05:30
commit da3b6cf083
1281 changed files with 97466 additions and 0 deletions

View File

@@ -0,0 +1,34 @@
using System;
#if UNITY_WEBGL
using System.Runtime.InteropServices;
#endif
namespace Mirror.SimpleWeb
{
internal static class SimpleWebJSLib
{
#if UNITY_WEBGL
[DllImport("__Internal")]
internal static extern bool IsConnected(int index);
#pragma warning disable CA2101 // Specify marshaling for P/Invoke string arguments
[DllImport("__Internal")]
#pragma warning restore CA2101 // Specify marshaling for P/Invoke string arguments
internal static extern int Connect(string address, Action<int> openCallback, Action<int> closeCallBack, Action<int, IntPtr, int> messageCallback, Action<int> errorCallback);
[DllImport("__Internal")]
internal static extern void Disconnect(int index);
[DllImport("__Internal")]
internal static extern bool Send(int index, byte[] array, int offset, int length);
#else
internal static bool IsConnected(int index) => throw new NotSupportedException();
internal static int Connect(string address, Action<int> openCallback, Action<int> closeCallBack, Action<int, IntPtr, int> messageCallback, Action<int> errorCallback) => throw new NotSupportedException();
internal static void Disconnect(int index) => throw new NotSupportedException();
internal static bool Send(int index, byte[] array, int offset, int length) => throw new NotSupportedException();
#endif
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 97b96a0b65c104443977473323c2ff35
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,141 @@
using System;
using System.Collections.Generic;
using AOT;
namespace Mirror.SimpleWeb
{
#if !UNITY_2021_3_OR_NEWER
// Unity 2019 doesn't have ArraySegment.ToArray() yet.
public static class Extensions
{
public static byte[] ToArray(this ArraySegment<byte> segment)
{
byte[] array = new byte[segment.Count];
Array.Copy(segment.Array, segment.Offset, array, 0, segment.Count);
return array;
}
}
#endif
public class WebSocketClientWebGl : SimpleWebClient
{
static readonly Dictionary<int, WebSocketClientWebGl> instances = new Dictionary<int, WebSocketClientWebGl>();
/// <summary>
/// key for instances sent between c# and js
/// </summary>
int index;
/// <summary>
/// Queue for messages sent by high level while still connecting, they will be sent after onOpen is called.
/// <para>
/// This is a workaround for anything that calls Send immediately after Connect.
/// Without this the JS websocket will give errors.
/// </para>
/// </summary>
Queue<byte[]> ConnectingSendQueue;
internal WebSocketClientWebGl(int maxMessageSize, int maxMessagesPerTick) : base(maxMessageSize, maxMessagesPerTick)
{
#if !UNITY_WEBGL || UNITY_EDITOR
throw new NotSupportedException();
#endif
}
public bool CheckJsConnected() => SimpleWebJSLib.IsConnected(index);
public override void Connect(Uri serverAddress)
{
index = SimpleWebJSLib.Connect(serverAddress.ToString(), OpenCallback, CloseCallBack, MessageCallback, ErrorCallback);
instances.Add(index, this);
state = ClientState.Connecting;
}
public override void Disconnect()
{
state = ClientState.Disconnecting;
// disconnect should cause closeCallback and OnDisconnect to be called
SimpleWebJSLib.Disconnect(index);
}
public override void Send(ArraySegment<byte> segment)
{
if (segment.Count > maxMessageSize)
{
Log.Error($"Cant send message with length {segment.Count} because it is over the max size of {maxMessageSize}");
return;
}
if (state == ClientState.Connected)
{
SimpleWebJSLib.Send(index, segment.Array, segment.Offset, segment.Count);
}
else
{
if (ConnectingSendQueue == null)
ConnectingSendQueue = new Queue<byte[]>();
ConnectingSendQueue.Enqueue(segment.ToArray());
}
}
void onOpen()
{
receiveQueue.Enqueue(new Message(EventType.Connected));
state = ClientState.Connected;
if (ConnectingSendQueue != null)
{
while (ConnectingSendQueue.Count > 0)
{
byte[] next = ConnectingSendQueue.Dequeue();
SimpleWebJSLib.Send(index, next, 0, next.Length);
}
ConnectingSendQueue = null;
}
}
void onClose()
{
// this code should be last in this class
receiveQueue.Enqueue(new Message(EventType.Disconnected));
state = ClientState.NotConnected;
instances.Remove(index);
}
void onMessage(IntPtr bufferPtr, int count)
{
try
{
ArrayBuffer buffer = bufferPool.Take(count);
buffer.CopyFrom(bufferPtr, count);
receiveQueue.Enqueue(new Message(buffer));
}
catch (Exception e)
{
Log.Error($"onData {e.GetType()}: {e.Message}\n{e.StackTrace}");
receiveQueue.Enqueue(new Message(e));
}
}
void onErr()
{
receiveQueue.Enqueue(new Message(new Exception("Javascript Websocket error")));
Disconnect();
}
[MonoPInvokeCallback(typeof(Action<int>))]
static void OpenCallback(int index) => instances[index].onOpen();
[MonoPInvokeCallback(typeof(Action<int>))]
static void CloseCallBack(int index) => instances[index].onClose();
[MonoPInvokeCallback(typeof(Action<int, IntPtr, int>))]
static void MessageCallback(int index, IntPtr bufferPtr, int count) => instances[index].onMessage(bufferPtr, count);
[MonoPInvokeCallback(typeof(Action<int>))]
static void ErrorCallback(int index) => instances[index].onErr();
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 015c5b1915fd1a64cbe36444d16b2f7d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1999985791b91b9458059e88404885a7
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,114 @@
// this will create a global object
const SimpleWeb = {
webSockets: [],
next: 1,
GetWebSocket: function (index) {
return SimpleWeb.webSockets[index]
},
AddNextSocket: function (webSocket) {
var index = SimpleWeb.next;
SimpleWeb.next++;
SimpleWeb.webSockets[index] = webSocket;
return index;
},
RemoveSocket: function (index) {
SimpleWeb.webSockets[index] = undefined;
},
};
function IsConnected(index) {
var webSocket = SimpleWeb.GetWebSocket(index);
if (webSocket) {
return webSocket.readyState === webSocket.OPEN;
}
else {
return false;
}
}
function Connect(addressPtr, openCallbackPtr, closeCallBackPtr, messageCallbackPtr, errorCallbackPtr) {
// fix for unity 2021 because unity bug in .jslib
if (typeof Runtime === "undefined") {
// if unity doesn't create Runtime, then make it here
// dont ask why this works, just be happy that it does
Runtime = {
dynCall: dynCall
}
}
const address = UTF8ToString(addressPtr);
console.log("Connecting to " + address);
// Create webSocket connection.
webSocket = new WebSocket(address);
webSocket.binaryType = 'arraybuffer';
const index = SimpleWeb.AddNextSocket(webSocket);
// Connection opened
webSocket.addEventListener('open', function (event) {
console.log("Connected to " + address);
Runtime.dynCall('vi', openCallbackPtr, [index]);
});
webSocket.addEventListener('close', function (event) {
console.log("Disconnected from " + address);
Runtime.dynCall('vi', closeCallBackPtr, [index]);
});
// Listen for messages
webSocket.addEventListener('message', function (event) {
if (event.data instanceof ArrayBuffer) {
// TODO dont alloc each time
var array = new Uint8Array(event.data);
var arrayLength = array.length;
var bufferPtr = _malloc(arrayLength);
var dataBuffer = new Uint8Array(HEAPU8.buffer, bufferPtr, arrayLength);
dataBuffer.set(array);
Runtime.dynCall('viii', messageCallbackPtr, [index, bufferPtr, arrayLength]);
_free(bufferPtr);
}
else {
console.error("message type not supported")
}
});
webSocket.addEventListener('error', function (event) {
console.error('Socket Error', event);
Runtime.dynCall('vi', errorCallbackPtr, [index]);
});
return index;
}
function Disconnect(index) {
var webSocket = SimpleWeb.GetWebSocket(index);
if (webSocket) {
webSocket.close(1000, "Disconnect Called by Mirror");
}
SimpleWeb.RemoveSocket(index);
}
function Send(index, arrayPtr, offset, length) {
var webSocket = SimpleWeb.GetWebSocket(index);
if (webSocket) {
const start = arrayPtr + offset;
const end = start + length;
const data = HEAPU8.buffer.slice(start, end);
webSocket.send(data);
return true;
}
return false;
}
const SimpleWebLib = {
$SimpleWeb: SimpleWeb,
IsConnected,
Connect,
Disconnect,
Send
};
autoAddDeps(SimpleWebLib, '$SimpleWeb');
mergeInto(LibraryManager.library, SimpleWebLib);

View File

@@ -0,0 +1,37 @@
fileFormatVersion: 2
guid: 54452a8c6d2ca9b49a8c79f81b50305c
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
Facebook: WebGL
second:
enabled: 1
settings: {}
- first:
WebGL: WebGL
second:
enabled: 1
settings: {}
userData:
assetBundleName:
assetBundleVariant: