Remote Player in Unity

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

Moderators: Lapo, Bax

charris456
Posts: 16
Joined: 03 Feb 2012, 02:08

Remote Player in Unity

Postby charris456 » 03 Feb 2012, 02:20

Hello,

I am new to SmartFox server, and I was wondering what would be the best way to identify Server -> Client messages for remote players.

I understand how to send and broadcast position updates for players, but I'm not sure how to identify remote players in unity. For example:

I am Client A, and I receive a Position/Rotation update, that was sent from the server, for Client B. I have a RemotePlayer script in Unity that would handle this, but what is the best way to identify which RemotePlayer to apply the new Position/Rotation update? I know each player has an ActorNumber in SmartFox, but in Unity, how could I choose the GameObject that equals that ActorNumber?

Further Info:
What I would like to have is a RemotePlayer Prefab in unity. I know when a new player joins, I will need to Instantiate this RemotePlayer Prefab in script. However, when I receive a RemotePlayer position update, I'm not sure how I would identify which GameObject created receives that update. I know I could assign a variable in that Prefab like ActorNumber, but how would I find it with gameOjbect.find to update it's position?

Thanks for any help, or any links to tutorials which may help.
charris456
Posts: 16
Joined: 03 Feb 2012, 02:08

Postby charris456 » 03 Feb 2012, 03:19

Actually I figured this out, I think (sorry I didn't do my research hard enough!).

I can instantiate the RemotePlayer prefab then set it's name by doing remotePlayer.name = "remote" + ActorNumber;

Then I can do a gameObject.find("remote"+ActorNumber) when a remote player position update is sent from the server.

Is this right?
Jake-GR
Posts: 59
Joined: 28 Dec 2011, 22:52

Postby Jake-GR » 03 Feb 2012, 05:08

I use a Dictionary<> object, that has the SmartFox User.Name as the key, and the instantiated GameObject as the value (handle very similar to the FPS Unity demo)
charris456
Posts: 16
Joined: 03 Feb 2012, 02:08

Postby charris456 » 04 Feb 2012, 11:39

Thanks Jake! That sounds better than my idea.

BTW, I got started with your tutorials. Then went on to create a login extension using a database. Going to start with movement next, and wanted to go ahead and get a way to identify remote objects created.

Thanks again!
Jake-GR
Posts: 59
Joined: 28 Dec 2011, 22:52

Postby Jake-GR » 04 Feb 2012, 14:20

Thanks for watching, I haven't done anything with login extension yet (thats my next step) but Ive done some basic movement stuff (thats why I knew about Dictionary hehe)

But before I jump in, is it that complex to make a login extension with a mysql database?
charris456
Posts: 16
Joined: 03 Feb 2012, 02:08

Postby charris456 » 05 Feb 2012, 03:38

It was actually quite frustrating, until I made two simple changes.. Here is the code I used in my extension login handler:

Code: Select all

package com.warstruck.extension;

import java.sql.SQLException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.PreparedStatement;
import com.smartfoxserver.bitswarm.sessions.ISession;
import com.smartfoxserver.v2.entities.data.SFSArray;
import com.smartfoxserver.v2.db.SFSDBManager;
import com.smartfoxserver.v2.core.SFSEventParam;
import com.smartfoxserver.v2.core.ISFSEvent;
import com.smartfoxserver.v2.entities.data.SFSObject;
import com.smartfoxserver.v2.exceptions.SFSException;
import com.smartfoxserver.v2.exceptions.SFSLoginException;
import com.smartfoxserver.v2.exceptions.SFSErrorData;
import com.smartfoxserver.v2.exceptions.SFSErrorCode;
import com.smartfoxserver.v2.extensions.BaseServerEventHandler;
import com.smartfoxserver.v2.extensions.ExtensionLogLevel;

public class LoginHandler extends BaseServerEventHandler {

   @Override
   public void handleServerEvent(ISFSEvent event) throws SFSException
   {
        String username = (String) event.getParameter(SFSEventParam.LOGIN_NAME);
        String password = (String) event.getParameter(SFSEventParam.LOGIN_PASSWORD);
       
        //trace("Got '" + username + "' " + password);

        ISession session = (ISession)event.getParameter(SFSEventParam.SESSION);

        try {
            //get a connection to the database
            Connection conn = getParentExtension().getParentZone().getDBManager().getConnection();

            //This will strip potential SQL injections
            PreparedStatement sql = conn.prepareStatement("SELECT account_id, password FROM accounts WHERE username = ?");
            sql.setString(1, username);

            // Obtain ResultSet
            ResultSet result = sql.executeQuery();

            //Put the result into an SFSobject array
            SFSArray row = SFSArray.newFromResultSet(result);
     

            //make sure there is a password before you try to use the checkSecurePassword function
            if (password.equals(""))
            {
                SFSErrorData data = new SFSErrorData(SFSErrorCode.LOGIN_BAD_PASSWORD);
                data.addParameter(username);
                throw new SFSLoginException("You must enter a password.", data);
            }

           //SFS always encrypts passwords before sending them so you need to decrypt the password
           //received from the database and compare that to what they entered in flash
            if (row != null){
                if (row.size() > 0){
                    trace("Query was good");
                    if (!getApi().checkSecurePassword(session, row.getSFSObject(0).getUtfString("password"), password))
                    {
                            SFSErrorData data = new SFSErrorData(SFSErrorCode.LOGIN_BAD_PASSWORD);

                            data.addParameter(username);

                            throw new SFSLoginException("Login failed for user: "  + username, data);
                    }
                } else {
                    trace("Size was zero.");
                    SFSErrorData errData = new SFSErrorData(SFSErrorCode.LOGIN_BAD_PASSWORD);
                    throw new SFSLoginException("Row Size Zero", errData);
                }
            } else {
                    trace("Row was null.");
                    SFSErrorData errData = new SFSErrorData(SFSErrorCode.LOGIN_BAD_PASSWORD);
                    throw new SFSLoginException("Row was null", errData);
            }

            //make sure you close the database connection when you're done with it, especially if you've
            //set a low number of maximum connections
            conn.close();

            //at this point you could trigger an joinRoom request if you wanted to, otherwise
            //this will return success to your LOGIN event listener
            trace("Login successful, joining room!");

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


For some very odd reason, I found out that if I did not have the if statements for checking for if row was null, or greater than zero, it would error out with a "java.lang.IndexOutOfBoundsException: Index: 1, Size: 1," error when a player would login. Not sure if I'm doing something wrong, but this seems to work.[/code]
charris456
Posts: 16
Joined: 03 Feb 2012, 02:08

Postby charris456 » 05 Feb 2012, 03:43

In fact, after just looking at the code again, it should not work, since I'm getting the first value in the result array (0), which should be the account id. If anyone has any ideas why this is working, and what I'm doing wrong, I'd be most appreciative.

EDIT: Nevermind, just double checked and (0) does actually contain the correct password.. I'm used to PHP where mysql_result(0), would be the first column (account_id) in the select statement... Still not sure why it required the two if statements though..

Return to “SFS2X C# API”

Who is online

Users browsing this forum: No registered users and 77 guests