Page 1 of 1

Debugging My Extension

Posted: 14 Feb 2011, 17:38
by iceshaft07
I have no idea what I am doing wrong here.

I attempted to debug my extension using the Eclipse Remote Debugger Tool, but I am getting this strange error:

Code: Select all

BeerPongExtension [Remote Java Application]	
	Java HotSpot(TM) Client VM[169.254.169.154:8787]	
		Thread [main] (Suspended (exception ClassNotFoundException))	
			Launcher$AppClassLoader(URLClassLoader).findClass(String) line: 205	
			Launcher$AppClassLoader(ClassLoader).loadClass(String, boolean) line: 306	
			Launcher$AppClassLoader.loadClass(String, boolean) line: 268	
			Launcher$AppClassLoader(ClassLoader).loadClass(String) line: 251	
			Launcher$AppClassLoader(ClassLoader).loadClassInternal(String) line: 319	
The last line suggest that Arg [0] =

Code: Select all

com.smartfoxserver.v2.Main
If Arg[0] had said the classname I wrote, that would make more sense to me.

Is the above happening because I didn't define a Main in my Jar? I didn't think I had to.

Posted: 15 Feb 2011, 18:00
by iceshaft07
I've checked the manual thousands of times at this point, and I can't seem to find anyone having a similar issue on the forums. The only thing I can do now is hope someone sees something going on in this post to help me out.

Here is my directory structure for my extension (clientside)

Code: Select all

/src/com/robsmith/supergun/SuperGunExtension.java
/src/com/robsmith/supergun/handlers/SendPackedStringHandler.java
/src/com/robsmith/supergun/handlers/OnUserGoneHandler.java
/src/com/robsmith/supergun/utils/RoomHelper.java
/src/com/robsmith/supergun/utils/UserHelper.java
My extension is simple. It has two functions; forward a string sent from a client to all clients, and notify users when someone has left:

Code: Select all

//SuperGunExtension.java

package com.robsmith.supergun;

import com.smartfoxserver.v2.core.SFSEventType;
import com.smartfoxserver.v2.extensions.SFSExtension;
import com.robsmith.supergun.handlers.*;

// Requests that can be send from clients:
// - sendPackedString

public class SuperGunExtension extends SFSExtension 
{
    //	private World world; // Reference to World simulation model

    //	public World getWorld() {
    //		return world;
    //	}

	@Override
	public void init() {
	    //		world = new World(this);  // Creating the world model

		// Subscribing the request handlers
		addRequestHandler("SendPackedString", SendPackedStringHandler.class);

		addEventHandler(SFSEventType.USER_DISCONNECT, OnUserGoneHandler.class);
		addEventHandler(SFSEventType.USER_LEAVE_ROOM, OnUserGoneHandler.class);
		addEventHandler(SFSEventType.USER_LOGOUT, OnUserGoneHandler.class);

		trace("SuperGun extension initialized");
	}
	
	@Override
	public void destroy() {
		super.destroy();
	}
}

Code: Select all

//SendPackedStringHandler

package com.robsmith.supergun.handlers;

import com.robsmith.supergun.utils.RoomHelper;
import com.robsmith.supergun.utils.UserHelper;

import com.smartfoxserver.v2.entities.Room;
import com.smartfoxserver.v2.entities.User;
import com.smartfoxserver.v2.entities.data.ISFSObject;
import com.smartfoxserver.v2.extensions.BaseClientRequestHandler;

import java.util.List;

public class SendPackedStringHandler extends BaseClientRequestHandler {
    
    @Override
    public void handleClientRequest(User u, ISFSObject data) 
    {
    	//	String packedString = String.fromSFSObject(data);
    	
    	//	World world = RoomHelper.getWorld(this);
    	//	boolean valid = world.receivePackedString(u, receivedTransform);

    	//if (valid)
    	//    {
    	Room currentRoom = RoomHelper.getCurrentRoom(this);
    	List<User> userList = UserHelper.getRecipientsList(currentRoom);
    	this.send("SendPackedString", data, userList);
		//    }
    }
}

Code: Select all

//OnUserGoneHandler

package com.robsmith.supergun.handlers;

import com.smartfoxserver.v2.core.ISFSEvent;
import com.smartfoxserver.v2.exceptions.SFSException;
import com.smartfoxserver.v2.extensions.BaseServerEventHandler;


public class OnUserGoneHandler extends BaseServerEventHandler {

	@Override
	public void handleServerEvent(ISFSEvent event) throws SFSException {
//		User user = (User) event.getParameter(SFSEventParam.USER);
//		World world = RoomHelper.getCurrentRoom(this);
//		world.userLeft(user);
	}
}
The other two helper files remain unchanged from the sfsFps example, but I will provide them anyways:

Code: Select all

//RoomHelper

package com.robsmith.superpong.utils;

import com.smartfoxserver.v2.entities.Room;
import com.smartfoxserver.v2.extensions.BaseClientRequestHandler;
import com.smartfoxserver.v2.extensions.SFSExtension;


// Helper methods to easily get current room or zone and precache the link to ExtensionHelper
public class RoomHelper {

	public static Room getCurrentRoom(BaseClientRequestHandler handler) {
		return handler.getParentExtension().getParentRoom();
	}

	public static Room getCurrentRoom(SFSExtension extension) {
		return extension.getParentRoom();
	}
}

Code: Select all

package com.robsmith.supergun.utils;

import com.smartfoxserver.v2.entities.Room;
import com.smartfoxserver.v2.entities.User;

import java.util.List;

// Helper methods to easily get socket channel list to send response message to clients
public class UserHelper {


	public static List<User> getRecipientsList(Room room, User exceptUser) {
		List<User> users = room.getUserList();
		if (exceptUser != null) {
			users.remove(exceptUser);
		}

		return users;

	}

	public static List<User> getRecipientsList(Room currentRoom) {
		return getRecipientsList(currentRoom, null);
	}


}
I compiled the above into a .Jar using Eclipse on my Mac via:

Code: Select all

Package Explorer -> Right Click On SuperGunExtension -> Export
Select /Java/Jar File

NEXT

[X] Export Generated class files and resources
[ ] Export all output ...
[ ] Export Java sources ...
[ ] Export refactorings ...
Export Dstination /Users/robsmith/Desktop/SuperGunExtension.jar
[X] Compress contents of Jar
[ ] Add directory entreis
[ ] overwrite without warning

NEXT

[X] Export class fiels with compile errors
[X] Export class files with compile warnings
GREYED [ ] create source folder structure
GREYED [X] Build projects if not built automaticall
[X] Save description of this Jar in workspace
/SuperGunExtension/SuperGunExtension.jardesc

NEXT

(O) Generate Manifest File
    [ ] Save manifest in workspace
    GREYED [ ] Use the saved manifest...
    Manifest File:

( ) Use Existing manifest
    Manifest File:

( ) Seal the Jar
(O) Seal some packages          Nothing Sealed

Select the entry point:
(empty)

FINISH

My Server looks like this:

Code: Select all

/etc/sfs2x/SFS2X/extensions/supergun/SuperGunExtension.jar
sfsStartDebug looks like this

Code: Select all

java -Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y -cp "./:lib/*:lib/Jetty/*:extensions/__lib__/*" -Dfile.encoding=UT\
F-8 com.smartfoxserver.v2.Main $1 $2 $3
When executed, it reports:

Code: Select all

Listening for transport dt_socket at address: 8787
The eclipse Debug tool reports the above post when run:

Code: Select all

BeerPongExtension [Remote Java Application]   
   Java HotSpot(TM) Client VM[169.254.169.154:8787]   
      Thread [main] (Suspended (exception ClassNotFoundException))   
         Launcher$AppClassLoader(URLClassLoader).findClass(String) line: 205   
         Launcher$AppClassLoader(ClassLoader).loadClass(String, boolean) line: 306   
         Launcher$AppClassLoader.loadClass(String, boolean) line: 268   
         Launcher$AppClassLoader(ClassLoader).loadClass(String) line: 251   
         Launcher$AppClassLoader(ClassLoader).loadClassInternal(String) line: 319    

ARG[0] = com.smartfoxserver.v2.Main
When I run my unity project, I do not get any errors when trying to create the room with my extension (though, I don't get any when the extension isn't there either). Here is some code worth mentioning in my project:

Code: Select all

//Protocols/SmartFoxServer.js

... code ...

    public static var extName : String = "supergun";  // The server extension we work with
    public static var extClass : String = "com.robsmith.supergun.SuperGunExtension"; // The class name of the extension

    private var smartFox : SmartFox;
    private var useDebug : boolean = true;

    function Awake ()
    {
    	myName = gameObject.name;

	if (SmartFoxConnection.IsInitialized)
	{
	    smartFox = SmartFoxConnection.Connection;
	}
	else
	{
	    smartFox = new SmartFox(useDebug);
	}

	gameController = GameObject.Find("GameControl").GetComponent(GameController) as GameController;
	gameRules = gameObject.Find("GameRules").GetComponent(GameRules) as GameRules;
    }

... code ...

    function FixedUpdate () : void
    {
	if (gameController.GetGameState() == "Playing" || gameController.GetGameState() == "WaitingForSmartFox")
	{
	    if (running)
	    {
		if (firstRun)
		{
		    smartFox = SmartFoxConnection.Connection;
		    SubscribeDelegates();
		    firstRun = false;
		}
		else
		{
		    smartFox.ProcessEvents();
		}
	    }
	    else
	    {
		smartFox = SmartFoxConnection.Connection;
		
		if (smartFox != null)
		{
		    running = true;
		}
	    }
	}
    }

    function SubscribeDelegates () : void
    {
	smartFox.AddEventListener(SFSEvent.EXTENSION_RESPONSE, OnExtensionResponse);
	smartFox.AddEventListener(SFSEvent.USER_EXIT_ROOM, OnUserLeaveRoom);
	smartFox.AddEventListener(SFSEvent.CONNECTION_LOST, OnConnectionLost);
	smartFox.AddEventListener(SFSEvent.USER_COUNT_CHANGE, OnUserCountChange);
    }

    function Send (message : String)
    {
	var room : Room = smartFox.LastJoinedRoom;
	var data : ISFSObject = SFSObject();
	data.PutUtfString("msg", message);
	var request : ExtensionRequest = ExtensionRequest("sendPackedString", data, room);

	Debug.Log("Sending to " + room.Name + " " + room.Id + "::" + message);
	smartFox.Send(request);
    }

    // This method handles all the responses from the server
    function OnExtensionResponse (evt : BaseEvent) 
    {
	Debug.Log("RECEIVED:" + Utilities.HashtableToString(evt.Params));

	try 
	{
	    var cmd : String = evt.Params["cmd"].ToString();
	    CallFromPackedData(cmd);
	}
	catch (e : Exception) 
	{
	    Debug.Log("Exception handling response: "+e.Message+" >>> "+e.StackTrace);
	}
    }

Code: Select all

//Menus/MenuMultiplayerLobby.js (LobbyGUI.cs converted to .JS)

... code ...

	// Button row
	if (GUI.Button (new Rect (0, 70, 80, 20), "New game")) 
	{
	    showNewGameWindow = false;
	    
	    if (roomName.Equals("")) {
		roomName = smartFox.MySelf.Name + " game";
	    }

//tried uncommenting code below, didn't work
//	    var roomObj : NewRoomDescriptor = NewRoomDescriptor (roomName, numMaxUsers, true, 0, ArrayList(), nNewRoomDescriptor.ExtensionDescriptor(SmartFoxServer.extName, SmartFoxServer.extClass), "", true, true);
//	    smartFox.CreateRoom(roomObj);
	    

	    var settings : RoomSettings = new RoomSettings(roomName);
	    settings.GroupId = "game";
	    settings.IsGame = true;
	    settings.MaxUsers = numMaxUsers;
	    settings.MaxSpectators = 0;
	    settings.Extension = new RoomExtension(SmartFoxServer.extName, SmartFoxServer.extClass);
	    smartFox.Send(new CreateRoomRequest(settings, true, smartFox.LastJoinedRoom));

	    smartFox.RemoveAllEventListeners();

//	    menuController.SetMenu("WaitingForSmartFox");
	}

... code ...
I checked the documentation to see if there was a way to log debug in a file on the server and I did not see it. I checked the API to see if there was a function to do this and I did not see it. The trace function seemed only relevant to flash users. I checked to see where the main entery point for SFS was, which pointed stated "The main entry point of API is the com.smartfoxserver.v2.api.SFSApi class".

This makes me beleive I need to change com.smartfoxserver.v2.Main to com.smartfoxserver.v2.api.SFSApi.Main, but that didn't help.

I'm really lost, and I haven't had any luck finding anything over the past few days.

Any help is much appreciated.

Posted: 15 Feb 2011, 19:03
by tchen
iceshaft07 wrote: I checked the documentation to see if there was a way to log debug in a file on the server and I did not see it. I checked the API to see if there was a function to do this and I did not see it. The trace function seemed only relevant to flash users. I checked to see where the main entery point for SFS was, which pointed stated "The main entry point of API is the com.smartfoxserver.v2.api.SFSApi class".

This makes me beleive I need to change com.smartfoxserver.v2.Main to com.smartfoxserver.v2.api.SFSApi.Main, but that didn't help.

I'm really lost, and I haven't had any luck finding anything over the past few days.

Any help is much appreciated.
For logging, either use the trace methods on the BaseExtension / Base*Handlers, or import org.apache.log4j.*

Code: Select all

Logger.getLogger(myClass.class).trace("yadda yadda");
Also make sure your log4j.properties in the config folder are setup properly

Code: Select all

log4j.category.com.mydomain=TRACE,consoleAppender,fileAppender
I can't help you with the remote debugging though.

edited: Opps, i just realized you might have been asking for logging from client to server. I'll leave this here in case anyone else needs server logging.

Posted: 15 Feb 2011, 19:05
by iceshaft07
Awesome! That'll get me started again :-D!!

Posted: 15 Feb 2011, 19:17
by iceshaft07
I think I may have done something incredibly stupid...

Code: Select all

//in extension
addRequestHandler([b]"SendPackedString"[/b], SendPackedStringHandler.class); 

//in unity
   var request : ExtensionRequest = ExtensionRequest([b]"sendPackedString"[/b], data, room);

   Debug.Log("Sending to " + room.Name + " " + room.Id + "::" + message);
   smartFox.Send(request); 
Just retyping out the above and walking away for a minute seems to have done the trick... I see that I am receiving messages now :-)!