How to correctly deserialize a ByteArrays as an SFSObject on the client?

Post here your questions about the Unity / .Net / Mono / Windows 8 / Windows Phone 8 API for SFS2X

Moderators: Lapo, Bax

luiznsidiao
Posts: 13
Joined: 03 Aug 2019, 04:36

How to correctly deserialize a ByteArrays as an SFSObject on the client?

Postby luiznsidiao » 09 Aug 2019, 19:36

Hi, im trying to deserialize an SFSObject stored in my database.

I tried using newFromBinary but I don't know if I did it correctly.

Here is the code:

Client:

Code: Select all

    private void OnExtensionResponse(BaseEvent evt)
    {
        string cmd = (string)evt.Params["cmd"];

        if (cmd == "get position")
        {
            SFSObject dataIn = (SFSObject)evt.Params["params"];

            SFSObject deserializedData = SFSObject.NewFromBinaryData(dataIn.GetByteArray("params"));

            Debug.Log(deserializedData.GetDouble("posX"));
            Debug.Log(deserializedData.GetDouble("posY"));
            Debug.Log(deserializedData.GetDouble("posZ"));
        }
    }


Server Extension:

Code: Select all

public void handleClientRequest(User sender, ISFSObject params)
    {
       String username = sender.getName().toString();
       
        try
        {
            SFSDBManager dbm = (SFSDBManager)this.getParentExtension().getParentZone().getDBManager();
            dbm.executeQuery("select lastposition from users where username = ?",
                  new Object[] { username });
           
            params.toBinary();
           
            this.send("get position", params, sender);
           
            trace(username + " last position data seleted. LOG: " + params.toString());
        }
        catch (Exception e)
        {
            e.printStackTrace();
            trace(e.getStackTrace().toString());
        }
    }
User avatar
Lapo
Site Admin
Posts: 23008
Joined: 21 Mar 2005, 09:50
Location: Italy

Re: How to correctly deserialize a ByteArrays as an SFSObject on the client?

Postby Lapo » 10 Aug 2019, 08:02

Hi,
yes you're doing it correctly :)

Cheers
Lapo
--
gotoAndPlay()
...addicted to flash games
luiznsidiao
Posts: 13
Joined: 03 Aug 2019, 04:36

Re: How to correctly deserialize a ByteArrays as an SFSObject on the client?

Postby luiznsidiao » 10 Aug 2019, 21:11

Thanks again Lapo! :D

I thought I was wrong because im getting this exception:

NullReferenceException: Object reference not set to an instance of an object
Sfs2X.Protocol.Serialization.DefaultSFSDataSerializer.Binary2Object (Sfs2X.Util.ByteArray data)

This exception is referring to line 100:

Code: Select all

SFSObject deserializedData = SFSObject.NewFromBinaryData(dataIn.GetByteArray("params"));


Requesting the data:

Code: Select all

private void OnJoinRoom(BaseEvent evt)
    {
        Room room = (Room)evt.Params["room"];
        SFSObject data = new SFSObject();

        Network.Client.Send(new ExtensionRequest("get position", data, room));       
    }
User avatar
Lapo
Site Admin
Posts: 23008
Joined: 21 Mar 2005, 09:50
Location: Italy

Re: How to correctly deserialize a ByteArrays as an SFSObject on the client?

Postby Lapo » 12 Aug 2019, 06:54

I would need to see the raw binary data to understand what the problem might be.
It seems like you're manually serializing/deserializing position data. Is there a specific reason to do this? Why not just simply send the data as numeric values in the SFSObject instead?

Also, minor suggestion, I would shorten the "get position" Extension command to avoid wasting data. 1-2 characters usually is enough, unless the game is slow paced (few reqs per second) in which case it probably won't matter.

Cheers
Lapo

--

gotoAndPlay()

...addicted to flash games
luiznsidiao
Posts: 13
Joined: 03 Aug 2019, 04:36

Re: How to correctly deserialize a ByteArrays as an SFSObject on the client?

Postby luiznsidiao » 12 Aug 2019, 19:20

Hi Lapo! How are you? :)

The reason for this is that I need to save a lot of data, so I may have to save around 25 variables. They will be saved and recovered only when the user logs in and when the application closes.

It seems like you're manually serializing/deserializing position data. Is there a specific reason to do this? Why not just simply send the data as numeric values in the SFSObject instead?

I researched the forum about saving data to the database and found something about saving SFSObject, i don't know if I understood very well, I think I needed to convert it to binary and here I am.

Also, minor suggestion, I would shorten the "get position" Extension command to avoid wasting data. 1-2 characters usually is enough, unless the game is slow paced (few reqs per second) in which case it probably won't matter.

Thanks for the tip!

Before I send SFSObject to the database I perform the function
ToBinary

SFSObject on binary column: Image
User avatar
Lapo
Site Admin
Posts: 23008
Joined: 21 Mar 2005, 09:50
Location: Italy

Re: How to correctly deserialize a ByteArrays as an SFSObject on the client?

Postby Lapo » 13 Aug 2019, 08:23

Thanks for the explanation.
In your server side code I see a couple of problems:

Code: Select all

public void handleClientRequest(User sender, ISFSObject params)
    {
       String username = sender.getName().toString();
       
        try
        {
            SFSDBManager dbm = (SFSDBManager)this.getParentExtension().getParentZone().getDBManager();
            dbm.executeQuery("select lastposition from users where username = ?",
                  new Object[] { username });
           
            params.toBinary();
           
            this.send("get position", params, sender);
           
            trace(username + " last position data seleted. LOG: " + params.toString());
        }
        catch (Exception e)
        {
            e.printStackTrace();
            trace(e.getStackTrace().toString());
        }
    }

For starters it's not very clear what the database query is supposed to do, as you execute the query but you don't process it. What is the point of running the query? Is the code incomplete?

Also the variable params represents the SFSObject passed to the handler.
It's not clear why you're calling params.toBinary(). This will return the encoded byte[] version but there is no variable assigned to it, so the data is just lost.

The client side part is also quite confusing, but let's leave it aside for now as I don't understand what you're trying to do on the server side, for starters. Can you clarify?

Thanks
Lapo

--

gotoAndPlay()

...addicted to flash games
luiznsidiao
Posts: 13
Joined: 03 Aug 2019, 04:36

Re: How to correctly deserialize a ByteArrays as an SFSObject on the client?

Postby luiznsidiao » 13 Aug 2019, 15:56

So I am trying to store data and retrieve it in game for use at runtime.

For example, when logging in the client retrieves the saved data from the database, that data would be last position, HP, experience, etc ...
When leaving the game the player sends the data as new values ​​to the server that updates the database. data.

As a beginner, I don't have a good idea how to do this, I'm researching some things but I'm not getting results.

Can you give me a hint as to what would be a good option for a real time game?

Should I use SFSObject and save it to binary in database?

Should I use explicit data in strings, int, floats...?

The reason I was using SFSObject was because I found a forum post saying that if you focus on storing a lot of data a good option would be to save SFSObject as binary.

About the code, I do not know if I should return the data already converted or convert it straight to the client.

If you have a better way of doing this, please tell me, I really have no idea how to solve this problem. :(
User avatar
Lapo
Site Admin
Posts: 23008
Joined: 21 Mar 2005, 09:50
Location: Italy

Re: How to correctly deserialize a ByteArrays as an SFSObject on the client?

Postby Lapo » 13 Aug 2019, 16:40

Thanks for the reiterating your scenario, I think it's pretty clear. However you did not address the questions I posted in the previous message. Can you please take a look and let us know?

Thanks
Lapo

--

gotoAndPlay()

...addicted to flash games
luiznsidiao
Posts: 13
Joined: 03 Aug 2019, 04:36

Re: How to correctly deserialize a ByteArrays as an SFSObject on the client?

Postby luiznsidiao » 13 Aug 2019, 18:29

Here are the answers:

For starters it's not very clear what the database query is supposed to do, as you execute the query but you don't process it. What is the point of running the query? Is the code incomplete?

I took a look and realized that not storing Query data, honestly I have no idea how to do it. So I think the code is incomplete because of my ignorance. :lol:

Also the variable params represents the SFSObject passed to the handler.
It's not clear why you're calling params.toBinary(). This will return the encoded byte[] version but there is no variable assigned to it, so the data is just lost.

I was trying to return params as binary data to the client when extension as requested.

The client side part is also quite confusing, but let's leave it aside for now as I don't understand what you're trying to do on the server side, for starters. Can you clarify?

I sent a converted SFSObject to binary, and then I try to retrieve it using a Query and I try to send the selected data back to the client through the extension response.

Thank you so much for helping! :D
User avatar
Lapo
Site Admin
Posts: 23008
Joined: 21 Mar 2005, 09:50
Location: Italy

Re: How to correctly deserialize a ByteArrays as an SFSObject on the client?

Postby Lapo » 14 Aug 2019, 07:24

luiznsidiao wrote:I took a look and realized that not storing Query data, honestly I have no idea how to do it. So I think the code is incomplete because of my ignorance. :lol:

Take a look at this example:
https://smartfoxserver.com/blog/queryin ... esultsets/

Also the variable params represents the SFSObject passed to the handler.
It's not clear why you're calling params.toBinary(). This will return the encoded byte[] version but there is no variable assigned to it, so the data is just lost.

I was trying to return params as binary data to the client when extension as requested.

You don't need to manually convert an SFSObject to binary. It's done by the API automatically (from both client and server side)
You just pass your SFSObject to the send() method and the everything is done for you behind the scenes. Furthermore the toBinary() method returns a byte[] which you're not even using. That's why I wasn't able to understand what was your goal in that method.

The client side part is also quite confusing, but let's leave it aside for now as I don't understand what you're trying to do on the server side, for starters. Can you clarify?

I sent a converted SFSObject to binary, and then I try to retrieve it using a Query and I try to send the selected data back to the client through the extension response.

I am still not following.

The client sends and SFSObject to the server. OK
Then you're trying to "retrieve it" using a query... retrieving what exactly? Something is missing :)

1) What does the client send exactly?
2) What do you look up in the database when you receive such data?

Keep in ming that all this can be done without worrying about binary encoding/decoding, because the client and server API already do it for you.
Lapo

--

gotoAndPlay()

...addicted to flash games
User avatar
Lapo
Site Admin
Posts: 23008
Joined: 21 Mar 2005, 09:50
Location: Italy

Re: How to correctly deserialize a ByteArrays as an SFSObject on the client?

Postby Lapo » 14 Aug 2019, 07:26

Lapo wrote:
luiznsidiao wrote:I took a look and realized that not storing Query data, honestly I have no idea how to do it. So I think the code is incomplete because of my ignorance. :lol:

Take a look at this example:
https://smartfoxserver.com/blog/queryin ... esultsets/

Also the variable params represents the SFSObject passed to the handler.
It's not clear why you're calling params.toBinary(). This will return the encoded byte[] version but there is no variable assigned to it, so the data is just lost.

I was trying to return params as binary data to the client when extension as requested.

You don't need to manually convert an SFSObject to binary. It's done by the API automatically (from both client and server side)
You just pass your SFSObject to the send() method and the everything is done for you behind the scenes. Furthermore the toBinary() method returns a byte[] which you're not even using. That's why I wasn't able to understand what was your goal in that method.

The client side part is also quite confusing, but let's leave it aside for now as I don't understand what you're trying to do on the server side, for starters. Can you clarify?

I sent a converted SFSObject to binary, and then I try to retrieve it using a Query and I try to send the selected data back to the client through the extension response.


The client sends and SFSObject to the server. OK
Then you're trying to "retrieve it" using a query... retrieving what exactly? Something is missing :)

1) What does the client send exactly?
2) What do you look up in the database when you receive such data?

Keep in ming that all this can be done without worrying about binary encoding/decoding, because the client and server API already do it for you.
Lapo

--

gotoAndPlay()

...addicted to flash games
User avatar
Lapo
Site Admin
Posts: 23008
Joined: 21 Mar 2005, 09:50
Location: Italy

Re: How to correctly deserialize a ByteArrays as an SFSObject on the client?

Postby Lapo » 14 Aug 2019, 07:27

luiznsidiao wrote:I took a look and realized that not storing Query data, honestly I have no idea how to do it. So I think the code is incomplete because of my ignorance. :lol:

Take a look at this example:
https://smartfoxserver.com/blog/queryin ... esultsets/

I was trying to return params as binary data to the client when extension as requested.

You don't need to manually convert an SFSObject to binary. It's done by the API automatically (from both client and server side)
You just pass your SFSObject to the send() method and the everything is done for you behind the scenes. Furthermore the toBinary() method returns a byte[] which you're not even using.

I sent a converted SFSObject to binary, and then I try to retrieve it using a Query and I try to send the selected data back to the client through the extension response.

The client sends and SFSObject to the server. OK
Then you're trying to "retrieve it" using a query... retrieving what exactly? Something is missing :)

1) What does the client send exactly?
2) What do you look up in the database when you receive such data?

Keep in ming that all this can be done without worrying about binary encoding/decoding, because the client and server API already do it for you.
Lapo

--

gotoAndPlay()

...addicted to flash games
luiznsidiao
Posts: 13
Joined: 03 Aug 2019, 04:36

Re: How to correctly deserialize a ByteArrays as an SFSObject on the client?

Postby luiznsidiao » 14 Aug 2019, 14:14

1) What does the client send exactly?

Code: Select all

 
    {
        SFSObject data = new SFSObject();

          posX = transform.position.x;
   posY = transform.position.y;
   posZ = transform.position.z;

        data.PutDouble"x", posX);
   data.PutDouble"y", posY);
   data.PutDouble"z", posZ);

        Network.Client.Send(new ExtensionRequest("set position", data, room));
    }
   


2) What do you look up in the database when you receive such data?

I look for the column in which the data was stored,but now that I've seen in the API example I need to use try catch. :lol:

I will apply the changes in the code, thanks!
luiznsidiao
Posts: 13
Joined: 03 Aug 2019, 04:36

Re: How to correctly deserialize a ByteArrays as an SFSObject on the client?

Postby luiznsidiao » 15 Aug 2019, 04:56

I am trying to do something like this post: viewtopic.php?t=13977

I already stored the data as BLOB:
Image

Extension UPDATE:

Code: Select all

public void handleClientRequest(User sender, ISFSObject params)
    {
        try
        {
            SFSDBManager dbm = (SFSDBManager) getParentExtension().getParentZone().getDBManager();
            dbm.executeUpdate("UPDATE users SET data=? WHERE username=?",
                    new Object[] { params.toBinary() ,sender.getName() });
                    // I needed to return toBinary() to store in the BLOB column.
        }
        catch (Exception e)
        {
            trace(ExtensionLogLevel.WARN, "SQL Failed: " + e.toString());
        }
    }


Extension SELECT:

Code: Select all

public void handleClientRequest(User sender, ISFSObject isfsObject)
    {
        IDBManager dbManager = getParentExtension().getParentZone().getDBManager();
        String sql = "SELECT data FROM users WHERE username=?";
        try
        {
            ISFSArray queryResult = dbManager.executeQuery(sql, new Object[] { sender.getName()} );

            ISFSObject response = new SFSObject();
            response.putSFSArray("data", queryResult);

            send("gp", response, sender);
        }
        catch (SQLException e)
        {
            trace(ExtensionLogLevel.WARN, "SQL Failed: " + e.toString());
        }
    }


But now I'm getting a new exception, this time in the client:
Image

Code that throws the exception on the client:

Code: Select all

    private void OnExtensionResponse(BaseEvent evt)
    {
        string cmd = (string)evt.Params["cmd"];
       
        if (cmd == "gp")
        {
            ISFSObject dataIn = (SFSObject)evt.Params["params"];
            ISFSObject deserializedData = SFSObject.NewFromBinaryData(dataIn.GetByteArray("data"));
            // I tried to use params in getBinary Array, but get null exception. Should I use the parameters as "data"?
           
            Debug.Log(deserializedData.GetDouble("posX"));
            Debug.Log(deserializedData.GetDouble("posY"));
            Debug.Log(deserializedData.GetDouble("posZ"));
        }
    }


There is not an exception in the sfs2x instance or log files.

I really have no idea how to save and get data without having to create a specific column for each type in the database. Something that was supposed to be simple is frying my head. :mrgreen:
User avatar
Lapo
Site Admin
Posts: 23008
Joined: 21 Mar 2005, 09:50
Location: Italy

Re: How to correctly deserialize a ByteArrays as an SFSObject on the client?

Postby Lapo » 16 Aug 2019, 08:38

The problem is on the client side.
From server side you are sending an SFSArray wrapped in an SFSObject, but on client side you're not dealing with this structure.

You're trying to extract a ByteArray from the top SFSObject when instead you have an SFSArray. Also the SFSArray contains the rows returned by the query, so you have to dig deeper into the data structure.

It looks like you didn't even check the example I gave you:
https://smartfoxserver.com/blog/queryin ... esultsets/

Since you're new to this, please take the time to actually understand the example. Trying to this blindly is just going to be frustrating.

My suggestion is to extract the ByteArray you need directly from the server side result-set and send only that to the client.

Cheers
Lapo

--

gotoAndPlay()

...addicted to flash games

Return to “SFS2X C# API”

Who is online

Users browsing this forum: No registered users and 29 guests