Closed yty closed 8 months ago
Have you found any update regarding this, I am also not able to convert the + callback in unity!
I created something to help with this:
file: ColyseusLobby.cs
using System;
using System.Threading.Tasks;
using Colyseus;
using GameDevWare.Serialization;
using System.Reflection;
public class ColyseusLobby
{
private readonly ColyseusClient _client;
public ColyseusRoom<dynamic> room;
public event Action<ColyseusRoomAvailable[]> OnRooms;
public event Action<string, ColyseusRoomAvailable> OnAddRoom;
public event Action<string> OnRemoveRoom;
public ColyseusLobby(ColyseusClient client)
{
_client = client;
}
public async Task Connect()
{
room = await _client.JoinOrCreate("lobby");
room.OnMessage<ColyseusRoomAvailable[]>("rooms", OnRoomsMessage);
room.OnMessage<object[]>("+", OnAddRoomMessage);
room.OnMessage<string>("-", OnRemoveRoomMessage);
}
void OnRoomsMessage(ColyseusRoomAvailable[] rooms)
{
OnRooms?.Invoke(rooms);
}
private T ConvertData<T>(ref T obj, FieldInfo[] fields, IndexedDictionary<string, object> data)
{
foreach (FieldInfo field in fields)
{
if (data.ContainsKey(field.Name))
{
data.TryGetValue(field.Name, out object value);
if (value is IndexedDictionary<string, object> indexedDictionary)
{
object fieldValue = Activator.CreateInstance(field.FieldType);
field.SetValue(obj, ConvertData(ref fieldValue, field.FieldType.GetFields(), indexedDictionary));
}
else if (field.FieldType == value.GetType())
{
field.SetValue(obj, value);
}
}
}
return obj;
}
void OnAddRoomMessage(object[] info)
{
var roomId = (string)info[0];
var data = (IndexedDictionary<string, object>)info[1];
var roomInfo = new ColyseusRoomAvailable();
var roomType = typeof(ColyseusRoomAvailable);
FieldInfo[] fields = roomType.GetFields();
ConvertData(ref roomInfo, fields, data);
OnAddRoom?.Invoke(roomId, roomInfo);
}
void OnRemoveRoomMessage(string roomId)
{
OnRemoveRoom?.Invoke(roomId);
}
}
File: LobbyExample.cs
using System.Collections;
using System.Collections.Generic;
using Colyseus;
using UnityEngine;
public class LobbyExample : MonoBehaviour
{
public ColyseusClient client;
void Start()
{
Connect();
}
async void Connect()
{
client = new ColyseusClient("ws://localhost:3000");
ColyseusLobby lobby = new ColyseusLobby(client);
await lobby.Connect();
lobby.OnRooms += (rooms) =>
{
Debug.Log("Rooms: " + rooms.Length);
};
lobby.OnAddRoom += (roomId, roomInfo) =>
{
Debug.Log("Add Room: " + roomId + " " + roomInfo.name);
};
lobby.OnRemoveRoom += (roomId) =>
{
Debug.Log("Remove Room: " + roomId);
};
}
}
That's worked like a charm! Thanks buddy @rbatistajs
我创建了一些东西来帮助解决这个问题:
文件:ColyseusLobby.cs
using System; using System.Threading.Tasks; using Colyseus; using GameDevWare.Serialization; using System.Reflection; public class ColyseusLobby { private readonly ColyseusClient _client; public ColyseusRoom<dynamic> room; public event Action<ColyseusRoomAvailable[]> OnRooms; public event Action<string, ColyseusRoomAvailable> OnAddRoom; public event Action<string> OnRemoveRoom; public ColyseusLobby(ColyseusClient client) { _client = client; } public async Task Connect() { room = await _client.JoinOrCreate("lobby"); room.OnMessage<ColyseusRoomAvailable[]>("rooms", OnRoomsMessage); room.OnMessage<object[]>("+", OnAddRoomMessage); room.OnMessage<string>("-", OnRemoveRoomMessage); } void OnRoomsMessage(ColyseusRoomAvailable[] rooms) { OnRooms?.Invoke(rooms); } private T ConvertData<T>(ref T obj, FieldInfo[] fields, IndexedDictionary<string, object> data) { foreach (FieldInfo field in fields) { if (data.ContainsKey(field.Name)) { data.TryGetValue(field.Name, out object value); if (value is IndexedDictionary<string, object> indexedDictionary) { object fieldValue = Activator.CreateInstance(field.FieldType); field.SetValue(obj, ConvertData(ref fieldValue, field.FieldType.GetFields(), indexedDictionary)); } else if (field.FieldType == value.GetType()) { field.SetValue(obj, value); } } } return obj; } void OnAddRoomMessage(object[] info) { var roomId = (string)info[0]; var data = (IndexedDictionary<string, object>)info[1]; var roomInfo = new ColyseusRoomAvailable(); var roomType = typeof(ColyseusRoomAvailable); FieldInfo[] fields = roomType.GetFields(); ConvertData(ref roomInfo, fields, data); OnAddRoom?.Invoke(roomId, roomInfo); } void OnRemoveRoomMessage(string roomId) { OnRemoveRoom?.Invoke(roomId); } }
文件:大厅示例.cs
using System.Collections; using System.Collections.Generic; using Colyseus; using UnityEngine; public class LobbyExample : MonoBehaviour { public ColyseusClient client; void Start() { Connect(); } async void Connect() { client = new ColyseusClient("ws://localhost:3000"); ColyseusLobby lobby = new ColyseusLobby(client); await lobby.Connect(); lobby.OnRooms += (rooms) => { Debug.Log("Rooms: " + rooms.Length); }; lobby.OnAddRoom += (roomId, roomInfo) => { Debug.Log("Add Room: " + roomId + " " + roomInfo.name); }; lobby.OnRemoveRoom += (roomId) => { Debug.Log("Remove Room: " + roomId); }; } }
@rbatistajs Man, that was great! Thank you for sharing...
I try to reproduce this example in unity. https://github.com/colyseus/colyseus-examples/blob/master/src/static/05-lobby-room.html
Q1: this error occurs
InvalidCastException: Specified cast is not valid.
Q2: And how to convert this syntax?
Thanks.