Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

0.15 #177

Merged
merged 23 commits into from
May 4, 2023
Merged

0.15 #177

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
f7fc868
refactoring schema callbacks. renaming files for clarity
endel Oct 22, 2021
3f6b0cf
refactoring schema callbacks. adding support for per-field callbacks.
endel Oct 27, 2021
827d44b
add triggerAll option for OnAdd callbacks. refactor test suite to use…
endel Oct 27, 2021
fb7339c
soft-deprecate .Id in favor of .RoomId
endel Oct 27, 2021
f74a962
rename 'Colyseus*' from file names for clarity
endel Nov 4, 2021
37ab4cb
fixes server build
endel Nov 9, 2021
d65b664
allow to connect directly to room endpoint via .publicAddress
endel Nov 9, 2021
d5dea43
support calling OnRemove() when clearing collections
endel Nov 18, 2021
a43699a
support for new private reconnection token
endel Nov 25, 2021
6014eda
re-generate test-suite schemas
endel Dec 17, 2021
6723254
Merge branch 'master' into 0.15
endel Dec 23, 2021
d82b7a8
post-merge #179. use 4300+ for local error codes
endel Dec 23, 2021
3088e93
re-generate test schema files
endel Mar 4, 2022
28d35eb
add support for Protocol.ROOM_DATA_BYTES
endel Mar 4, 2022
b8c6f33
fix TriggerChanges() due to bad __refId references
endel Mar 9, 2022
a9ede67
fixes triggering individual property changes
endel Mar 9, 2022
3a1f3bb
fix WebGL build on Unity 2021
endel Mar 9, 2022
a5f5522
fixes assigning refId to schema structures, and triggering OnRemove d…
endel Mar 17, 2022
46fe6cf
devMode Integration (#194)
allion-lahirup Jun 17, 2022
cb0f160
avoid unused variable warning
endel Jun 17, 2022
067dd06
fix triggering OnLeave when devMode=false
endel Jun 17, 2022
f35b893
Merge branch 'master' into 0.15
endel May 2, 2023
ee43556
update unit tests, refactoring
endel May 3, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
indent_style = tab
indent_style = space
indent_size = 4

[*.{js,ts}]
indent_style = space
indent_size = 2

[*.{cs}]
indent_style = tab
indent_style = space
indent_size = 4
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
# Server build files
Server/build

#User Specific
*.userprefs
*.usertasks
.DS_Store
.vs/
.vsconfig

#Mono Project Files
*.pidb
Expand Down
8 changes: 8 additions & 0 deletions Assets/Colyseus/Editor Default Resources.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
namespace Colyseus
{
/// <summary>
/// Base manager class
/// Base manager class
/// </summary>
/// <typeparam name="T"></typeparam>
public class ColyseusManager<T> : MonoBehaviour
Expand Down Expand Up @@ -146,4 +146,4 @@ protected virtual void OnApplicationQuit()
{
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -159,17 +159,16 @@ public async Task<ColyseusRoom<T>> JoinById<T>(string roomId, Dictionary<string,
/// <summary>
/// Reconnect to a <see cref="ColyseusRoom{T}" />
/// </summary>
/// <param name="roomId">ID of the room</param>
/// <param name="sessionId">Previously connected sessionId</param>
/// <param name="reconnectionToken">Previously connected ReconnectionToken</param>
/// <param name="headers">Dictionary of headers to pass to the server when we reconnect to the room</param>
/// <typeparam name="T">Type of <see cref="ColyseusRoom{T}" /> we want to reconnect with</typeparam>
/// <returns><see cref="ColyseusRoom{T}" /> via async task</returns>
public async Task<ColyseusRoom<T>> Reconnect<T>(string roomId, string sessionId,
public async Task<ColyseusRoom<T>> Reconnect<T>(ReconnectionToken reconnectionToken,
Dictionary<string, string> headers = null)
{
Dictionary<string, object> options = new Dictionary<string, object>();
options.Add("sessionId", sessionId);
return await CreateMatchMakeRequest<T>("joinById", roomId, options, headers);
options.Add("reconnectionToken", reconnectionToken.Token);
return await CreateMatchMakeRequest<T>("reconnect", reconnectionToken.RoomId, options, headers);
}

//
Expand Down Expand Up @@ -285,43 +284,86 @@ await colyseusRequest.Request("GET", $"matchmake/{roomName}", null,
/// </summary>
/// <param name="response">The response from the matchmaking attempt</param>
/// <param name="headers">Dictionary of headers to pass to the server</param>
/// <param name="previousRoom">Previous ColyseusRoom{T} instance to re-establish the server connection: Please do not use this devMode param for general purposes</param>
/// <typeparam name="T">Type of <see cref="ColyseusRoom{T}" /> we're consuming the seat from</typeparam>
/// <returns><see cref="ColyseusRoom{T}" /> in which we now have a seat via async task</returns>
public async Task<ColyseusRoom<T>> ConsumeSeatReservation<T>(ColyseusMatchMakeResponse response,
Dictionary<string, string> headers = null)
Dictionary<string, string> headers = null, ColyseusRoom<T> previousRoom = null)
{
ColyseusRoom<T> room = new ColyseusRoom<T>(response.room.name)
{
Id = response.room.roomId,
RoomId = response.room.roomId,
SessionId = response.sessionId
};

Dictionary<string, object> queryString = new Dictionary<string, object>();
queryString.Add("sessionId", room.SessionId);

room.SetConnection(CreateConnection(response.room.processId + "/" + room.Id, queryString, headers));
// forward reconnection token
if (room.ReconnectionToken != null)
{
queryString.Add("reconnectionToken", room.ReconnectionToken);
}

ColyseusRoom<T> targetRoom = previousRoom ?? room;

async void DevModeCloseCallback()
{
LSLog.Log($"[Colyseus devMode]: Re-establishing connection with room id {targetRoom.RoomId}");
int devModeRetryAttempt = 0;
const int devModeMaxRetryCount = 8;

async Task retryConnection()
{
devModeRetryAttempt++;
try
{
await ConsumeSeatReservation<T>(response, headers, targetRoom);
LSLog.Log($"[Colyseus devMode]: Successfully re-established connection with room {targetRoom.RoomId}");
}
catch (Exception)
{
if (devModeRetryAttempt < devModeMaxRetryCount)
{
LSLog.Log($"[Colyseus devMode]: retrying... ({devModeRetryAttempt} out of {devModeMaxRetryCount})");
await Task.Delay(2000);
await retryConnection();
}
else
{
LSLog.Log($"[Colyseus devMode]: Failed to reconnect! Is your server running? Please check server logs!");
}
}
}

await Task.Delay(2000);
await retryConnection();
}

targetRoom.SetConnection(CreateConnection(response.room, queryString, headers), targetRoom, response.devMode? DevModeCloseCallback
: null);

TaskCompletionSource<ColyseusRoom<T>> tcs = new TaskCompletionSource<ColyseusRoom<T>>();

void OnError(int code, string message)
{
room.OnError -= OnError;
tcs.SetException(new CSAMatchMakeException(code, message));
targetRoom.OnError -= OnError;
tcs.SetException(new MatchMakeException(code, message));
}

void OnJoin()
{
room.OnError -= OnError;
tcs.TrySetResult(room);
targetRoom.OnError -= OnError;
tcs.TrySetResult(targetRoom);
}

room.OnError += OnError;
room.OnJoin += OnJoin;
targetRoom.OnError += OnError;
targetRoom.OnJoin += OnJoin;

onAddRoom?.Invoke(room);
onAddRoom?.Invoke(targetRoom);

#pragma warning disable 4014
room.Connect();
targetRoom.Connect();
#pragma warning restore 4014

return await tcs.Task;
Expand All @@ -337,7 +379,7 @@ void OnJoin()
/// <typeparam name="T">Type of <see cref="ColyseusRoom{T}" /> we want to match with</typeparam>
/// <returns><see cref="ColyseusRoom{T}" /> we have matched with via async task</returns>
/// <exception cref="Exception">Thrown if there is a network related error</exception>
/// <exception cref="CSAMatchMakeException">Thrown if there is an error in the match making process on the server side</exception>
/// <exception cref="MatchMakeException">Thrown if there is an error in the match making process on the server side</exception>
protected async Task<ColyseusRoom<T>> CreateMatchMakeRequest<T>(string method, string roomName,
Dictionary<string, object> options, Dictionary<string, string> headers)
{
Expand All @@ -353,16 +395,22 @@ protected async Task<ColyseusRoom<T>> CreateMatchMakeRequest<T>(string method, s

string json = await colyseusRequest.Request("POST", $"matchmake/{method}/{roomName}", options, headers);
LSLog.Log($"Server Response: {json}");
ColyseusMatchMakeResponse response =
JsonUtility.FromJson<ColyseusMatchMakeResponse>(json);

ColyseusMatchMakeResponse response = JsonUtility.FromJson<ColyseusMatchMakeResponse>(json);
if (response == null)
{
throw new Exception($"Error with request: {json}");
}

if (!string.IsNullOrEmpty(response.error))
{
throw new CSAMatchMakeException(response.code, response.error);
throw new MatchMakeException(response.code, response.error);
}

// forward reconnection token on reconnect
if (method == "reconnect")
{
response.reconnectionToken = (string)options["reconnectionToken"];
}

return await ConsumeSeatReservation<T>(response, headers);
Expand All @@ -375,7 +423,7 @@ protected async Task<ColyseusRoom<T>> CreateMatchMakeRequest<T>(string method, s
/// <param name="options">Dictionary of options to use when connecting</param>
/// <param name="headers">Dictionary of headers to pass when connecting</param>
/// <returns></returns>
protected ColyseusConnection CreateConnection(string path = "", Dictionary<string, object> options = null,
protected ColyseusConnection CreateConnection(ColyseusRoomAvailable room, Dictionary<string, object> options = null,
Dictionary<string, string> headers = null)
{
if (options == null)
Expand All @@ -389,10 +437,21 @@ protected ColyseusConnection CreateConnection(string path = "", Dictionary<strin
list.Add(item.Key + "=" + (item.Value != null ? Convert.ToString(item.Value) : "null"));
}

var uriBuilder = colyseusRequest.GetUriBuilder(path, string.Join("&", list.ToArray()));
uriBuilder.Scheme = Endpoint.Scheme;
// Try to connect directly to custom publicAddress, if present.
var endpoint = (room.publicAddress != null && room.publicAddress.Length > 0)
? new Uri($"{Endpoint.Scheme}://{room.publicAddress}")
: Endpoint.Uri;

UriBuilder uriBuilder = new UriBuilder(endpoint)
{
Path = $"{room.processId}/{room.roomId}",
Query = string.Join("&", list.ToArray())
};

// FIXME?: regression from https://github.com/colyseus/colyseus-unity-sdk/pull/184
// var uriBuilder = colyseusRequest.GetUriBuilder(path, string.Join("&", list.ToArray()));

return new ColyseusConnection(uriBuilder.ToString(), headers);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ public class ColyseusErrorCode
/// <summary>
/// When local schema is different from schema on the server.
/// </summary>
public static int SCHEMA_MISMATCH = 4217;
public static int SCHEMA_MISMATCH = 4300;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ public class ColyseusProtocol
/// </summary>
public static byte ROOM_DATA_SCHEMA = 16;

public static byte ROOM_DATA_BYTES = 17;

//
// Matchmaking messages (20~30)
//
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,25 +35,25 @@ public async Task<string> Request(string uriMethod, string uriPath, string uriQu
{
req.uploadHandler = data;
}

foreach (KeyValuePair<string, string> 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();

#if UNITY_2020_1_OR_NEWER
if (req.result == UnityWebRequest.Result.ConnectionError || req.result == UnityWebRequest.Result.ProtocolError)
#else
if (req.isNetworkError || req.isHttpError)
if (req.isNetworkError || req.isHttpError)
#endif
{
if (_serverSettings.useSecureProtocol)
Expand All @@ -68,16 +68,16 @@ public async Task<string> Request(string uriMethod, string uriPath, string uriQu
throw new Exception(req.error);
}
}

string json = req.downloadHandler.text;

return json;
} ;
}

public async Task<string> Request(string uriMethod, string uriPath, Dictionary<string, object> options = null, Dictionary<string, string> headers = null)
{
using (UnityWebRequest req = new UnityWebRequest())
using (UnityWebRequest req = new UnityWebRequest())
{
req.method = uriMethod;
req.url = GetWebRequestURL(uriPath);
Expand All @@ -87,26 +87,26 @@ public async Task<string> Request(string uriMethod, string uriPath, Dictionary<s
// Send JSON options on request body
MemoryStream jsonBodyStream = new MemoryStream();
Json.Serialize(options, jsonBodyStream); //TODO: Replace GameDevWare serialization

req.uploadHandler = new UploadHandlerRaw(jsonBodyStream.ToArray())
{
contentType = "application/json"
};
}

foreach (KeyValuePair<string, string> pair in _serverSettings.HeadersDictionary)
{
req.SetRequestHeader(pair.Key, pair.Value);
}

if (headers != null)
{
foreach (KeyValuePair<string, string> header in headers)
{
req.SetRequestHeader(header.Key, header.Value);
}
}

req.downloadHandler = new DownloadHandlerBuffer();
await req.SendWebRequest();

Expand All @@ -128,13 +128,13 @@ public async Task<string> Request(string uriMethod, string uriPath, Dictionary<s
throw new Exception(req.error);
}
}

return req.downloadHandler.text;
};
}

public UriBuilder GetUriBuilder(string path, string query = "")
{
{
string forwardSlash = "";

if (!_serverSettings.WebRequestEndpoint.EndsWith("/"))
Expand All @@ -156,5 +156,5 @@ public string GetWebRequestURL(string path, string query = "")

return GetUriBuilder(path, query).ToString();
}
}
}
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,12 @@ public class ColyseusMatchMakeResponse
/// Session ID used for connection to the room
/// </summary>
public string sessionId;

public string reconnectionToken;

/// <summary>
/// Establish server connection after server reloading
/// </summary>
public Boolean devMode;
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading