diff --git a/Assets/Colyseus/Runtime/Example~/Scenes/LobbyScene.unity b/Assets/Colyseus/Runtime/Example~/Scenes/LobbyScene.unity index dc02c8d3..b0f96fc9 100644 Binary files a/Assets/Colyseus/Runtime/Example~/Scenes/LobbyScene.unity and b/Assets/Colyseus/Runtime/Example~/Scenes/LobbyScene.unity differ diff --git a/Assets/Colyseus/Runtime/Example~/Scripts/ExampleRoomController.cs b/Assets/Colyseus/Runtime/Example~/Scripts/ExampleRoomController.cs index ed966838..9562c984 100644 --- a/Assets/Colyseus/Runtime/Example~/Scripts/ExampleRoomController.cs +++ b/Assets/Colyseus/Runtime/Example~/Scripts/ExampleRoomController.cs @@ -7,6 +7,7 @@ using GameDevWare.Serialization; using LucidSightTools; using NativeWebSocket; +using Settings; using UnityEngine; /// @@ -136,6 +137,11 @@ public class ExampleRoomController /// public List rooms = new List(); + private Action DisposeNetworkEntitiesOnAdd; + private Action DisposeNetworkEntitiesOnRemove; + private Action DisposeNetworkedUsersOnAdd; + private Action DisposeNetworkedUsersOnRemove; + /// /// Returns the synchronized time from the server in milliseconds. /// @@ -295,7 +301,7 @@ public async Task CreateSpecificRoom(ColyseusClient client, string roomName, str } onComplete?.Invoke(true); - LSLog.LogImportant($"Created Room: {_room.Id}"); + LSLog.LogImportant($"Created Room: {_room.RoomId}"); _lastRoomId = roomId; RegisterRoomHandlers(); } @@ -326,8 +332,8 @@ public async Task JoinOrCreateRoom(Action onComplete = null) } onComplete?.Invoke(true); - LSLog.LogImportant($"Joined / Created Room: {_room.Id}"); - _lastRoomId = _room.Id; + LSLog.LogImportant($"Joined / Created Room: {_room.RoomId}"); + _lastRoomId = _room.RoomId; RegisterRoomHandlers(); } @@ -396,14 +402,12 @@ public virtual void RegisterRoomHandlers() //_room.OnMessage("messageNameInCustomLogic", objectOfTypeYOUR_CUSTOM_MESSAGE => { }); //======================== - _room.State.networkedEntities.OnAdd += OnEntityAdd; - _room.State.networkedEntities.OnRemove += OnEntityRemoved; - - _room.State.networkedUsers.OnAdd += OnUserAdd; - _room.State.networkedUsers.OnRemove += OnUserRemove; + this.DisposeNetworkEntitiesOnAdd = _room.State.networkedEntities.OnAdd(OnEntityAdd); + this.DisposeNetworkEntitiesOnRemove = _room.State.networkedEntities.OnRemove(OnEntityRemoved); - _room.State.TriggerAll(); - //======================== + this.DisposeNetworkedUsersOnAdd = _room.State.networkedUsers.OnAdd(OnUserAdd); + this.DisposeNetworkedUsersOnRemove = _room.State.networkedUsers.OnRemove(OnUserRemove); + _room.colyseusConnection.OnError += Room_OnError; _room.colyseusConnection.OnClose += Room_OnClose; @@ -439,10 +443,10 @@ private void ClearRoomHandlers() return; } - _room.State.networkedEntities.OnAdd -= OnEntityAdd; - _room.State.networkedEntities.OnRemove -= OnEntityRemoved; - _room.State.networkedUsers.OnAdd -= OnUserAdd; - _room.State.networkedUsers.OnRemove -= OnUserRemove; + this.DisposeNetworkEntitiesOnAdd(); + this.DisposeNetworkEntitiesOnRemove(); + this.DisposeNetworkedUsersOnAdd(); + this.DisposeNetworkedUsersOnRemove(); _room.colyseusConnection.OnError -= Room_OnError; _room.colyseusConnection.OnClose -= Room_OnClose; @@ -564,7 +568,7 @@ private void OnUserAdd(string key, ExampleNetworkedUser user) _users.Add(key, user); // On entity update... - user.OnChange += changes => + user.OnChange(() => { user.updateHash = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString(); @@ -574,7 +578,7 @@ private void OnUserAdd(string key, ExampleNetworkedUser user) { OnCurrentUserStateChanged?.Invoke(user.attributes); } - }; + }); } /// diff --git a/Assets/Colyseus/Runtime/Example~/Scripts/Lobby/UI/CreateUserMenu.cs b/Assets/Colyseus/Runtime/Example~/Scripts/Lobby/UI/CreateUserMenu.cs index 5af1d12c..7fc8f129 100644 --- a/Assets/Colyseus/Runtime/Example~/Scripts/Lobby/UI/CreateUserMenu.cs +++ b/Assets/Colyseus/Runtime/Example~/Scripts/Lobby/UI/CreateUserMenu.cs @@ -29,7 +29,7 @@ public string ServerURL { return serverURLInput.text; } - + return ExampleManager.Instance.ColyseusServerAddress; } } diff --git a/Assets/Colyseus/Runtime/Example~/Scripts/Lobby/UI/LobbyController.cs b/Assets/Colyseus/Runtime/Example~/Scripts/Lobby/UI/LobbyController.cs index c43c183d..4d3067ca 100644 --- a/Assets/Colyseus/Runtime/Example~/Scripts/Lobby/UI/LobbyController.cs +++ b/Assets/Colyseus/Runtime/Example~/Scripts/Lobby/UI/LobbyController.cs @@ -1,7 +1,9 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using Colyseus; +using LucidSightTools; +using Settings; using UnityEngine; using UnityEngine.SceneManagement; diff --git a/Assets/Colyseus/Runtime/Example~/Scripts/Views/ExampleNetworkedEntityView.cs b/Assets/Colyseus/Runtime/Example~/Scripts/Views/ExampleNetworkedEntityView.cs index 5e3dbce2..384cbacc 100644 --- a/Assets/Colyseus/Runtime/Example~/Scripts/Views/ExampleNetworkedEntityView.cs +++ b/Assets/Colyseus/Runtime/Example~/Scripts/Views/ExampleNetworkedEntityView.cs @@ -132,8 +132,8 @@ public void InitiView(ExampleNetworkedEntity entity) { state = entity; IsMine = ExampleManager.Instance.CurrentUser != null && string.Equals(ExampleManager.Instance.CurrentUser.sessionId, state.ownerId); - state.attributes.OnChange += Attributes_OnChange; - state.OnChange += Entity_State_OnChange; + state.attributes.OnChange(Attributes_OnChange); + state.OnChange(Entity_State_OnChange); OwnerId = state.ownerId; Id = state.id; @@ -168,7 +168,7 @@ public virtual void OnEntityRemoved() // Entity removed from room state; } - virtual protected void Entity_State_OnChange(List changes) + virtual protected void Entity_State_OnChange() { // Only record state change has been updated locally lastStateTimestamp = state.timestamp; diff --git a/Assets/Colyseus/Runtime/Example~/Settings/ColyseusSettings.asset b/Assets/Colyseus/Runtime/Example~/Settings/ColyseusSettings.asset index ffb9e825..9706b7f7 100644 --- a/Assets/Colyseus/Runtime/Example~/Settings/ColyseusSettings.asset +++ b/Assets/Colyseus/Runtime/Example~/Settings/ColyseusSettings.asset @@ -9,7 +9,7 @@ MonoBehaviour: m_GameObject: {fileID: 0} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: abda5a440b0b5634b8654ff3a0129b80, type: 3} + m_Script: {fileID: 11500000, guid: 6ed729989615d4b4db072e1e8c41076c, type: 3} m_Name: ColyseusSettings m_EditorClassIdentifier: colyseusServerAddress: localhost @@ -19,4 +19,4 @@ MonoBehaviour: - name: Content-Type value: application/json - name: Accept - value: application/json + value: application/json \ No newline at end of file diff --git a/Assets/Colyseus/Runtime/Example~/Settings/ColyseusSettings.asset.meta b/Assets/Colyseus/Runtime/Example~/Settings/ColyseusSettings.asset.meta index 855dae91..cd596a0f 100644 --- a/Assets/Colyseus/Runtime/Example~/Settings/ColyseusSettings.asset.meta +++ b/Assets/Colyseus/Runtime/Example~/Settings/ColyseusSettings.asset.meta @@ -1,8 +1,8 @@ fileFormatVersion: 2 -guid: 5fbf227f540d0384993aafa75df60613 +guid: 988e7a981629a46488c4facbf7657d29 NativeFormatImporter: externalObjects: {} - mainObjectFileID: 0 + mainObjectFileID: 11400000 userData: assetBundleName: assetBundleVariant: diff --git a/Assets/Colyseus/Runtime/Scripts/Managers/ColyseusManager.cs b/Assets/Colyseus/Runtime/Scripts/Managers/ColyseusManager.cs index bfac4205..6f59fe7f 100644 --- a/Assets/Colyseus/Runtime/Scripts/Managers/ColyseusManager.cs +++ b/Assets/Colyseus/Runtime/Scripts/Managers/ColyseusManager.cs @@ -1,12 +1,11 @@ -using System.Collections.Generic; -using LucidSightTools; +using Settings; using UnityEngine; // ReSharper disable InconsistentNaming namespace Colyseus { /// - /// Base manager class + /// Base manager class /// /// public class ColyseusManager : MonoBehaviour @@ -15,7 +14,7 @@ public class ColyseusManager : MonoBehaviour /// Reference to the Colyseus settings object. /// [SerializeField] - protected ColyseusSettings _colyseusSettings; + protected static ColyseusSettings _colyseusSettings; // Getters //========================== @@ -30,7 +29,7 @@ public class ColyseusManager : MonoBehaviour /// public string ColyseusServerAddress { - get { return _colyseusSettings.colyseusServerAddress; } + get { return _colyseusSettings.colyseusServerAddress; } } /// @@ -84,6 +83,7 @@ private void InitializeInstance() } Instance = GetComponent(); + _colyseusSettings = ScriptableObject.CreateInstance(); } /// diff --git a/Assets/Colyseus/Runtime/Scripts/Models/ColyseusClient.cs b/Assets/Colyseus/Runtime/Scripts/Models/ColyseusClient.cs index 5a6f3d78..0eb75112 100644 --- a/Assets/Colyseus/Runtime/Scripts/Models/ColyseusClient.cs +++ b/Assets/Colyseus/Runtime/Scripts/Models/ColyseusClient.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using LucidSightTools; +using Settings; using UnityEngine; // ReSharper disable InconsistentNaming diff --git a/Assets/Colyseus/Runtime/Scripts/Request.cs b/Assets/Colyseus/Runtime/Scripts/Request.cs index ffc2ec5b..ec35b080 100644 --- a/Assets/Colyseus/Runtime/Scripts/Request.cs +++ b/Assets/Colyseus/Runtime/Scripts/Request.cs @@ -8,6 +8,7 @@ using System.IO; using GameDevWare.Serialization; using LucidSightTools; +using Settings; namespace Colyseus { @@ -32,24 +33,24 @@ public async Task Request(string uriMethod, string uriPath, string uriQu using (UnityWebRequest req = new UnityWebRequest()) { req.method = uriMethod; - + req.url = uriBuilder.Uri.ToString(); // Send JSON on request body if (data != null) { req.uploadHandler = data; } - + foreach (KeyValuePair pair in _serverSettings.HeadersDictionary) { req.SetRequestHeader(pair.Key, pair.Value); } - + if (!string.IsNullOrEmpty(Token)) { req.SetRequestHeader("Authorization", "Bearer " + Token); } - + // req.uploadHandler = new UploadHandlerRaw(bytes); req.downloadHandler = new DownloadHandlerBuffer(); await req.SendWebRequest(); @@ -72,9 +73,9 @@ public async Task Request(string uriMethod, string uriPath, string uriQu throw new Exception(req.error); } } - + string json = req.downloadHandler.text; - + return json; } ; } @@ -94,18 +95,18 @@ public async Task Request(string uriMethod, string uriPath, Dictionary pair in _serverSettings.HeadersDictionary) { req.SetRequestHeader(pair.Key, pair.Value); } - + if (headers != null) { foreach (KeyValuePair header in headers) @@ -113,7 +114,7 @@ public async Task Request(string uriMethod, string uriPath, Dictionary Request(string uriMethod, string uriPath, Dictionary __callbacks.OnChange -= handler; } + public void AddToOnChange(OnChangeEventHandler handler) + { + __callbacks.OnChange += handler; + } + /// /// Attaches a callback that is triggered whenever this Schema instance has been removed from the server. /// diff --git a/Assets/Colyseus/Runtime/Scripts/Settings/ColyseusSettings.cs b/Assets/Colyseus/Runtime/Scripts/Settings/ColyseusSettings.cs new file mode 100644 index 00000000..c7c26be6 --- /dev/null +++ b/Assets/Colyseus/Runtime/Scripts/Settings/ColyseusSettings.cs @@ -0,0 +1,128 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace Settings +{ + /// + /// containing relevant Colyseus settings + /// + [CreateAssetMenu(fileName = "MyServerSettings", menuName = "Colyseus/Generate ColyseusSettings Scriptable Object", order = 1)] + [Serializable] + public class ColyseusSettings : ScriptableObject + { + /// + /// The server address + /// + public string colyseusServerAddress = "localhost"; + + /// + /// The port to connect to + /// + public string colyseusServerPort = "2567"; + + /// + /// If true, we use secure protocols (wss, https) otherwise we use ws, http (based on ) + /// + public bool useSecureProtocol = false; + + /// + /// Internal wrapper class for a Request header since Unity cant serialize arrays + /// + [Serializable] + public class RequestHeader + { + public string name; + public string value; + } + + [SerializeField] + private RequestHeader[] _requestHeaders; + + private Dictionary _headersDictionary; + + public void SetRequestHeaders(RequestHeader[] headers) + { + if (headers == null) return; + _requestHeaders = new RequestHeader[headers.Length]; + for (int i = 0; i < headers.Length; i++) + { + _requestHeaders[i] = headers[i]; + } + } + + public RequestHeader[] GetRequestHeaders() + { + return _requestHeaders; + } + + /// + /// Convert the user-defined into a dictionary to be used in a + /// + public Dictionary HeadersDictionary + { + get + { + if (_headersDictionary == null) + { + _headersDictionary = new Dictionary(); + + for (int i = 0; _requestHeaders != null && i < _requestHeaders.Length; ++i) + { + _headersDictionary.Add(_requestHeaders[i].name, _requestHeaders[i].value); + } + } + + return _headersDictionary; + } + } + + /// + /// Centralized location to build and return the WebSocketEndpoint + /// + public string WebSocketEndpoint + { + get + { + if (string.IsNullOrEmpty(colyseusServerPort) || colyseusServerPort.Equals(("80"))) + { + return (useSecureProtocol ? "wss" : "ws") + "://" + colyseusServerAddress; + } + + return (useSecureProtocol ? "wss" : "ws") + "://" + colyseusServerAddress + ":" + colyseusServerPort; + } + } + + /// + /// Centralized location to build and return an WebSocketEndpoint ignoring WS/WSS protocols for Unity Web Requests + /// + public string WebRequestEndpoint + { + get + { + if (string.IsNullOrEmpty(colyseusServerPort) || colyseusServerPort.Equals(("80"))) + { + return (useSecureProtocol ? "https" : "http") + "://" + colyseusServerAddress; + } + + return (useSecureProtocol ? "https" : "http") + "://" + colyseusServerAddress + ":" + colyseusServerPort; + } + } + + /// + /// Create a copy of the provided object + /// + /// The settings to copy + /// A new instance of with values copied from the provided object + public static ColyseusSettings Clone(ColyseusSettings orig) + { + ColyseusSettings clone = CreateInstance(); + clone.colyseusServerAddress = orig.colyseusServerAddress; + clone.colyseusServerPort = orig.colyseusServerPort; + clone.useSecureProtocol = orig.useSecureProtocol; + clone.SetRequestHeaders(orig.GetRequestHeaders()); + + return clone; + } + } +} \ No newline at end of file diff --git a/Assets/Colyseus/Runtime/Scripts/Settings/ColyseusSettings.cs.meta b/Assets/Colyseus/Runtime/Scripts/Settings/ColyseusSettings.cs.meta new file mode 100644 index 00000000..817b1186 --- /dev/null +++ b/Assets/Colyseus/Runtime/Scripts/Settings/ColyseusSettings.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6ed729989615d4b4db072e1e8c41076c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Server/package.json b/Server/package.json index 22cc3274..18a385e0 100644 --- a/Server/package.json +++ b/Server/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "my-app", - "version": "1.0.0", + "version": "1.1.0", "description": "npm init template for bootstrapping an empty Colyseus project", "main": "lib/index.js", "scripts": { @@ -19,21 +19,21 @@ }, "homepage": "https://github.com/colyseus/create-colyseus#readme", "devDependencies": { - "@colyseus/loadtest": "^0.14.7", - "@colyseus/redis-driver": "^0.14.22", + "@colyseus/loadtest": "^0.15.0-preview.0", + "@colyseus/redis-driver": "^0.15.0-preview.0", "@types/cors": "^2.8.6", "@types/express": "^4.17.1", "rimraf": "^2.7.1", - "ts-node": "^8.1.0", - "ts-node-dev": "^1.0.0-pre.63", - "typescript": "^3.4.5" + "ts-node": "^10.9.1", + "ts-node-dev": "^2.0.0", + "typescript": "^4.7.4" }, "dependencies": { - "@colyseus/arena": "^0.14.24", - "@colyseus/monitor": "^0.14.22", - "colyseus": "^0.14.23", + "@colyseus/arena": "^0.15.0-preview.1", + "@colyseus/monitor": "^0.15.0-preview.1", + "colyseus": "^0.15.0-preview.4", "cors": "^2.8.5", - "express": "^4.16.4", - "winston": "^3.3.3" + "express": "^4.18.1", + "winston": "^3.8.1" } }