[C#] ExpandoObject to Player Cast Exception (solved)

Alright. I am making a script that I want to release. On my event, it requires 3 arguments, 1 being a Player, and the other 2 being String. When I try to trigger my event using a chat message, it sends the error to the chat, that goes something like

Error invoking callback for event ds:newname: System.InvalidCastException: Could not cast event argument from ExpandoObject to Player
  at CitizenFX.Core.CallUtilities.<GetPassArguments>g__ChangeType0_0 (System.Object value, System.Type type) [0x00020] in /src/code/client/clrcore/EventHandlerDictionary.cs:121
  at CitizenFX.Core.CallUtilities.GetPassArguments (System.Reflection.MethodInfo method, System.Object[] args, System.String sourceString) [0x00085] in /src/code/client/clrcore/EventHandlerDictionary.cs:159
  at CitizenFX.Core.EventHandlerEntry+<Invoke>d__5.MoveNext () [0x00047] in /src/code/client/clrcore/EventHandlerDictionary.cs:84
CouldSending heartbeat to live-internal.fivem.net:30110

I don’t know why this is happening because there is nothing to cast, just the player to player in the event. I don’t know if this is happening to anyone else but this only happens to me when I do it to the class Player. It never happens when I put String or Int32 or Boolean. I find this very weird and it is limiting my progress on my script. I have tried to fix it for many days now but it just doesn’t want to work.

EDIT: If you have this issue yourself, don’t look at just the answer, read the rest of the comments below. They will help you too if you are on server side.

1 Like

send player.Handle, not player; events don’t actually pass objects directly as otherwise Lua/JS interop wouldn’t work

If I pass the handle which is a String how am I supposed to convert the handle back to the type of Player. I don’t see a constructor and the method that I am using this event in is not in the BaseScript class.

Just looked in the source and it seems you can just do Player player = new Player(handle)

Sorry that I never confirmed this before. I am on server side. On server side (for some reason) the player.Handle passes a String and not an Int32 and there is no constructor. I just downloaded the newest serverside version of CitizenFX.Core and it is still passing these things. Here is the code from my metadata:

    public class Player
    {
        public System.String Handle { get; }
        public System.String Name { get; }
        public System.Int32 Ping { get; }
        public System.Int32 LastMsg { get; }
        public IdentifierCollection Identifiers { get; }
        public System.String EndPoint { get; }

        public void Drop(System.String reason);
        public void TriggerEvent(System.String eventName, params System.Object[] args);
    }

I was looking at the source too and thought that it was weird that on there it passes an Int32 instead of a String like server side.

Well, in that case you might be better looping through the player list.

public Player getPlayer(String handle){
    foreach(Player plr in new PlayerList()){
        if(plr.handle == handle) return plr;
    }

    return null;
}
1 Like

I just thought there would be a better way of doing this than making my own method, I always that that there would be some sort of item in the Core’s code that would allow me to not make my own method. Thanks for the help anyway.

Hello,

I’ve found a workaround, aka if you wish to pass a class object through an event in C#, what you can do is, convert the class you want to pass to JSON and after you receive, store it in the same class by converting it back.

Example to pass the class

public class Player
{
     public string Name {get; set;}
     public string Email {get; set;}

     public PlayerSkin()
     {
           Name = "Kenth.";
     }
}

Player me = new Player();
// Now if you wanna pass it via triggerevent...

string playerData = JsonConvert.SerializeObject(me);
BaseScript.TriggerClientEvent("eventname",  playerData);

// And in the client class library that you share that class with just...
public void eventnamehandler(string playerData)
{
     Player me = new Player();
     me = JsonConvert.DeserializeObject<Player>(playerData);
}

Hope it helps someone.