colyseus / colyseus-unity-sdk

⚔ Colyseus Multiplayer SDK for Unity
https://docs.colyseus.io/getting-started/unity-sdk/
MIT License
371 stars 100 forks source link

Problems with lobbyRoom and ColyseusRoomAvailable. #208

Closed yty closed 8 months ago

yty commented 1 year ago

I try to reproduce this example in unity. https://github.com/colyseus/colyseus-examples/blob/master/src/static/05-lobby-room.html

    public async void Join()
    {
        await JoinOrCreateGame();
        GameRoom.OnJoin += GameRoom_OnJoin;
        GameRoom.OnLeave += GameRoom_OnLeave;
        Debug.Log("Joined lobby room!");
    }

    private void GameRoom_OnJoin()
    {
        GameRoom.OnMessage<ColyseusRoomAvailable>("rooms", rooms =>
        {

            //Update_full_list(rooms);
            Debug.Log("received full list of rooms:" + rooms.clients + "," + rooms.name + "," + rooms.processId + "," + rooms.roomId);
        });

        //GameRoom.OnMessage<string>("+", room =>
        // {
        //     Debug.Log("New room");
        // });

        //GameRoom.OnMessage<string>("-", room =>
        //{
        //    Debug.Log("Room removed");
        //});
    }

Q1: this error occurs InvalidCastException: Specified cast is not valid.

image

Q2: And how to convert this syntax?

lobby.onMessage("+", ([roomId, room]) => 

Thanks.

deveshbeniwal commented 10 months ago

Have you found any update regarding this, I am also not able to convert the + callback in unity!

rbatistajs commented 10 months ago

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);
        };
    }
}
deveshbeniwal commented 10 months ago

That's worked like a charm! Thanks buddy @rbatistajs

yty commented 8 months ago

我创建了一些东西来帮助解决这个问题:

文件: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...