Skip to content

Commit b4c2fc2

Browse files
authored
add unity components for webgl build (#20)
* add unity components for webgl build * add unity variable, unity logger, refactoring * remove unecessary import * reimplement unity client sdk * Resolve comments * use unity logger in EzyWSClient
1 parent 66b7a3b commit b4c2fc2

14 files changed

+960
-0
lines changed

jsproxy/proxy.jslib

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
var EzyFoxServerClientPlugin = {
2+
$ezy: {
3+
client: null,
4+
setup: null,
5+
setupApp: null,
6+
handshakeHandler: null,
7+
accessAppHandler: null,
8+
zoneName: null,
9+
appName: null,
10+
eventHandlerCallback: null,
11+
dataHandlerCallback: null,
12+
toUTF8: function (s) {
13+
var sLength = lengthBytesUTF8(s) + 1;
14+
var sPtr = _malloc(sLength);
15+
stringToUTF8(s, sPtr, sLength);
16+
return sPtr;
17+
},
18+
map: {
19+
'init': function (clientName, jsonConfig, callback) {
20+
var config = JSON.parse(jsonConfig);
21+
config.getClientName = function () {
22+
return this.clientName;
23+
}
24+
var clients = EzyClients.getInstance();
25+
ezy.client = clients.newClient(config);
26+
ezy.setup = ezy.client.setup;
27+
28+
for (var ezyEventType in EzyEventType) {
29+
if (EzyEventType.hasOwnProperty(ezyEventType)) {
30+
var eventHandler = {"ezyEventType": ezyEventType, "clientName": clientName};
31+
eventHandler.handle = function (event) {
32+
var jsonData = event ? JSON.stringify(event) : "{}";
33+
EzyLogger.console(this.clientName);
34+
EzyLogger.console(this.ezyEventType);
35+
EzyLogger.console(jsonData);
36+
dynCall_viii(
37+
ezy.eventHandlerCallback,
38+
ezy.toUTF8(this.clientName),
39+
ezy.toUTF8(this.ezyEventType),
40+
ezy.toUTF8(jsonData)
41+
);
42+
}
43+
ezy.setup.addEventHandler(ezyEventType, eventHandler);
44+
}
45+
}
46+
47+
for (var commandId in EzyCommands) {
48+
if (EzyCommands.hasOwnProperty(commandId)) {
49+
var dataHandler = {"cmd": EzyCommands[commandId], "clientName": clientName};
50+
dataHandler.handle = function (data) {
51+
var jsonData = data ? JSON.stringify(data) : "{}";
52+
EzyLogger.console(this.clientName);
53+
EzyLogger.console(this.cmd);
54+
EzyLogger.console(jsonData);
55+
dynCall_viii(
56+
ezy.dataHandlerCallback,
57+
ezy.toUTF8(this.clientName),
58+
this.cmd.id,
59+
ezy.toUTF8(jsonData)
60+
);
61+
}
62+
ezy.setup.addDataHandler(EzyCommands[commandId], dataHandler);
63+
}
64+
}
65+
66+
dynCall_vii(callback, ezy.toUTF8(clientName), ezy.toUTF8(jsonConfig));
67+
},
68+
'connect': function (clientName, jsonData, callback) {
69+
var data = JSON.parse(jsonData);
70+
ezy.client.connect(data.url);
71+
},
72+
'reconnect': function (clientName, callback) {
73+
EzyLogger.console('reconnect: clientName = ' + clientName);
74+
ezy.client.reconnect();
75+
},
76+
'disconnect': function (clientName, jsonData, callback) {
77+
EzyLogger.console('disconnect: clientName = ' + clientName + ', jsonData = ' + jsonData);
78+
var data = JSON.parse(jsonData);
79+
ezy.client.disconnect(data.reason);
80+
},
81+
'send': function (clientName, jsonData, callback) {
82+
var data = JSON.parse(jsonData);
83+
var cmd = EzyCommands[data.cmdId];
84+
var sendData = data.data;
85+
EzyClients.getInstance()
86+
.getClient(clientName)
87+
.send(cmd, sendData);
88+
},
89+
}
90+
},
91+
92+
setEventHandlerCallback: function (callback) {
93+
ezy.eventHandlerCallback = callback;
94+
},
95+
96+
setDataHandlerCallback: function (callback) {
97+
ezy.dataHandlerCallback = callback;
98+
},
99+
100+
setDebug: function (value) {
101+
EzyLogger.debug = value;
102+
},
103+
104+
run4: function (clientName, functionName, jsonData, callback) {
105+
var clientNameString = UTF8ToString(clientName);
106+
var functionNameString = UTF8ToString(functionName);
107+
var jsonDataString = UTF8ToString(jsonData);
108+
EzyLogger.console(
109+
'run4(clientName=' + clientNameString + ', functionName=' +
110+
functionNameString + ', jsonData=' + jsonDataString + ')'
111+
);
112+
ezy.map[functionNameString](clientNameString, jsonDataString, callback);
113+
},
114+
115+
run3: function (clientName, functionName, callback) {
116+
var clientNameString = UTF8ToString(clientName);
117+
var functionNameString = UTF8ToString(functionName);
118+
EzyLogger.console('run3(clientName=' + clientNameString + ', functionName=' + functionNameString + ')');
119+
ezy.map[functionNameString](clientNameString, callback);
120+
}
121+
};
122+
123+
autoAddDeps(EzyFoxServerClientPlugin, '$ezy');
124+
mergeInto(LibraryManager.library, EzyFoxServerClientPlugin);
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using System;
2+
using com.tvd12.ezyfoxserver.client.config;
3+
using Newtonsoft.Json;
4+
using Newtonsoft.Json.Linq;
5+
namespace Extensions.ezyfox_server_csharp_client.unity
6+
{
7+
public class EzyClientConfigJsonConverter : JsonConverter<EzyClientConfig>
8+
{
9+
public override void WriteJson(JsonWriter writer, EzyClientConfig clientConfig, JsonSerializer serializer)
10+
{
11+
JObject reconnectConfigJson = new JObject();
12+
EzyReconnectConfig reconnectConfig = clientConfig?.getReconnect();
13+
reconnectConfigJson.Add("enable", reconnectConfig?.isEnable());
14+
reconnectConfigJson.Add("maxReconnectCount", reconnectConfig?.getMaxReconnectCount());
15+
reconnectConfigJson.Add("reconnectPeriod", reconnectConfig?.getReconnectPeriod());
16+
17+
JObject pingJson = new JObject();
18+
EzyPingConfig pingConfig = clientConfig?.getPing();
19+
pingJson.Add("pingPeriod", pingConfig?.getPingPeriod());
20+
pingJson.Add("maxLostPingCount", pingConfig?.getMaxLostPingCount());
21+
22+
JObject clientConfigJson = new JObject();
23+
clientConfigJson.Add("zoneName", clientConfig?.getZoneName());
24+
clientConfigJson.Add("clientName", clientConfig?.getClientName());
25+
clientConfigJson.Add("reconnect", reconnectConfigJson);
26+
clientConfigJson.Add("ping", pingJson);
27+
28+
clientConfigJson.WriteTo(writer);
29+
}
30+
31+
public override EzyClientConfig? ReadJson(JsonReader reader, Type objectType, EzyClientConfig? existingValue, bool hasExistingValue,
32+
JsonSerializer serializer)
33+
{
34+
throw new NotImplementedException("Unnecessary because CanRead is false. The type will skip the converter.");
35+
}
36+
37+
public override bool CanRead => false;
38+
}
39+
}

unity/EzyClientFactory.cs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using com.tvd12.ezyfoxserver.client.config;
2+
3+
namespace com.tvd12.ezyfoxserver.client.unity
4+
{
5+
public sealed class EzyClientFactory
6+
{
7+
private static readonly EzyClientFactory INSTANCE = new();
8+
9+
private EzyClientFactory()
10+
{
11+
}
12+
13+
public static EzyClientFactory getInstance()
14+
{
15+
return INSTANCE;
16+
}
17+
18+
public EzyClient getOrCreateClient(EzyClientConfig config, bool udpUsage)
19+
{
20+
var ezyClients = EzyClients.getInstance();
21+
var ezyClient = ezyClients.getClient(config.getZoneName());
22+
if (ezyClient != null)
23+
{
24+
return ezyClient;
25+
}
26+
#if UNITY_WEBGL && !UNITY_EDITOR
27+
EzyWSClient ezyWsClient = new EzyWSClient(config);
28+
ezyClients.addClient(ezyWsClient);
29+
ezyWsClient.init();
30+
return ezyWsClient;
31+
#else
32+
if (udpUsage)
33+
{
34+
ezyClient = new EzyUTClient(config);
35+
}
36+
else
37+
{
38+
ezyClient = new EzyTcpClient(config);
39+
}
40+
ezyClients.addClient(ezyClient);
41+
return ezyClient;
42+
#endif
43+
}
44+
}
45+
}

unity/EzyDefaultController.cs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using com.tvd12.ezyfoxserver.client.config;
4+
using com.tvd12.ezyfoxserver.client.logger;
5+
using com.tvd12.ezyfoxserver.client.support;
6+
using UnityEngine;
7+
using Object = System.Object;
8+
9+
namespace com.tvd12.ezyfoxserver.client.unity
10+
{
11+
public class EzyDefaultController : MonoBehaviour
12+
{
13+
[SerializeField]
14+
protected EzySocketConfigVariable socketConfigVariable;
15+
protected EzySocketProxy socketProxy;
16+
protected EzyAppProxy appProxy;
17+
18+
private readonly List<Tuple<String, Object>> handlers = new();
19+
20+
protected static readonly EzyLogger LOGGER = EzyUnityLoggerFactory.getLogger<EzyDefaultController>();
21+
22+
protected void Start()
23+
{
24+
LOGGER.debug("Start");
25+
var socketProxyManager = EzySocketProxyManager.getInstance();
26+
if (!socketProxyManager.hasInited())
27+
{
28+
socketProxyManager.init();
29+
}
30+
socketProxy = socketProxyManager.getSocketProxy(socketConfigVariable.Value.ZoneName);
31+
if (socketProxy.getClient() == null)
32+
{
33+
LOGGER.debug("Creating ezyClient");
34+
var config = EzyClientConfig.builder()
35+
.clientName(socketConfigVariable.Value.ZoneName)
36+
.zoneName(socketConfigVariable.Value.ZoneName)
37+
.build();
38+
EzyClientFactory.getInstance()
39+
.getOrCreateClient(config, socketConfigVariable.Value.UdpUsage);
40+
}
41+
appProxy = socketProxy.getAppProxy(socketConfigVariable.Value.AppName, true);
42+
}
43+
44+
protected void on<T>(String cmd, EzyAppProxyDataHandler<T> handler)
45+
{
46+
handlers.Add(
47+
new Tuple<String, Object>(cmd, appProxy.on(cmd, handler))
48+
);
49+
}
50+
51+
protected virtual void OnDestroy()
52+
{
53+
LOGGER.debug("OnDestroy");
54+
foreach (Tuple<String, Object> tuple in handlers)
55+
{
56+
appProxy.unbind(tuple.Item1, tuple.Item2);
57+
}
58+
}
59+
}
60+
}

unity/EzyDelegates.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System;
2+
namespace com.tvd12.ezyfoxserver.client.unity
3+
{
4+
public class EzyDelegates
5+
{
6+
public delegate void Delegate1(String clientName);
7+
public delegate void Delegate2(String clientName, String jsonData);
8+
public delegate void EventHandlerDelegate(String clientName, String eventType, String jsonData);
9+
public delegate void DataHandlerDelegate(String clientName, int commandId, String jsonData);
10+
}
11+
}

unity/EzyEventProcessor.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using UnityEngine;
2+
3+
namespace com.tvd12.ezyfoxserver.client.unity
4+
{
5+
public class EzyEventProcessor : MonoBehaviour
6+
{
7+
private static EzyEventProcessor INSTANCE;
8+
9+
[SerializeField]
10+
private EzySocketConfigVariable socketConfig;
11+
12+
private void Awake()
13+
{
14+
// If go back to current scene, don't make duplication
15+
if (INSTANCE != null)
16+
{
17+
Destroy(gameObject);
18+
}
19+
else
20+
{
21+
INSTANCE = this;
22+
DontDestroyOnLoad(gameObject);
23+
}
24+
}
25+
26+
void Update()
27+
{
28+
// Main thread pulls data from socket
29+
#if UNITY_WEBGL && !UNITY_EDITOR
30+
#else
31+
EzyClients.getInstance()
32+
.getClient(socketConfig.Value.ZoneName)
33+
.processEvents();
34+
#endif
35+
}
36+
}
37+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using com.tvd12.ezyfoxserver.client.constant;
4+
using com.tvd12.ezyfoxserver.client.evt;
5+
using Newtonsoft.Json;
6+
7+
namespace com.tvd12.ezyfoxserver.client.unity
8+
{
9+
public sealed class EzyEventWSDataDeserializer
10+
{
11+
private static readonly Dictionary<String, EzyEventType> EVENT_TYPE_BY_STRING_VALUE = new()
12+
{
13+
{ "CONNECTION_SUCCESS", EzyEventType.CONNECTION_SUCCESS },
14+
{ "CONNECTION_FAILURE", EzyEventType.CONNECTION_FAILURE },
15+
{ "DISCONNECTION", EzyEventType.DISCONNECTION },
16+
{ "LOST_PING", EzyEventType.LOST_PING },
17+
{ "TRY_CONNECT", EzyEventType.TRY_CONNECT },
18+
};
19+
20+
private static readonly Dictionary<String, EzyConnectionFailedReason> CONNECTION_FAILED_REASON_BY_STRING_VALUE = new()
21+
{
22+
{ "TIME_OUT", EzyConnectionFailedReason.TIME_OUT },
23+
{ "NETWORK_UNREACHABLE", EzyConnectionFailedReason.NETWORK_UNREACHABLE },
24+
{ "UNKNOWN_HOST", EzyConnectionFailedReason.UNKNOWN_HOST },
25+
{ "CONNECTION_REFUSED", EzyConnectionFailedReason.CONNECTION_REFUSED },
26+
{ "UNKNOWN", EzyConnectionFailedReason.UNKNOWN },
27+
};
28+
29+
private static readonly Dictionary<EzyEventType, EventDeserializer> DESERIALIZER_BY_EVENT_TYPE = new()
30+
{
31+
{ EzyEventType.CONNECTION_SUCCESS, _ => new EzyConnectionSuccessEvent() },
32+
{
33+
EzyEventType.CONNECTION_FAILURE, jsonData => new EzyConnectionFailureEvent(
34+
CONNECTION_FAILED_REASON_BY_STRING_VALUE[
35+
JsonConvert.DeserializeObject<Dictionary<String, String>>(jsonData)
36+
.GetValueOrDefault("reason", "UNKNOWN")
37+
]
38+
)
39+
},
40+
{
41+
EzyEventType.DISCONNECTION, jsonData => new EzyDisconnectionEvent(
42+
JsonConvert.DeserializeObject<Dictionary<String, int>>(jsonData)
43+
.GetValueOrDefault("reason", 0)
44+
)
45+
},
46+
{
47+
EzyEventType.LOST_PING, jsonData => new EzyLostPingEvent(
48+
JsonConvert.DeserializeObject<Dictionary<String, int>>(jsonData)
49+
.GetValueOrDefault("count", 0)
50+
)
51+
},
52+
{
53+
EzyEventType.TRY_CONNECT, jsonData => new EzyTryConnectEvent(
54+
JsonConvert.DeserializeObject<Dictionary<String, int>>(jsonData)
55+
.GetValueOrDefault("count", 0)
56+
)
57+
}
58+
};
59+
private delegate EzyEvent EventDeserializer(String jsonData);
60+
private static readonly EzyEventWSDataDeserializer INSTANCE = new();
61+
62+
public static EzyEventWSDataDeserializer getInstance()
63+
{
64+
return INSTANCE;
65+
}
66+
67+
public EzyEvent deserializeEvent(String eventTypeStringValue, String jsonData)
68+
{
69+
var eventType = EVENT_TYPE_BY_STRING_VALUE[eventTypeStringValue];
70+
return DESERIALIZER_BY_EVENT_TYPE[eventType].Invoke(jsonData);
71+
}
72+
}
73+
}

0 commit comments

Comments
 (0)