Chat Tutorial in NetBeans/Text Client: Difference between revisions

From Arianne
Jump to navigation Jump to search
Content deleted Content added
imported>SimonSmall
Extra logging info
imported>SimonSmall
 
(29 intermediate revisions by the same user not shown)
Line 4: Line 4:


For more detail in using the NetBeans IDE, see the [[Using and configuring NetBeans]] page.
For more detail in using the NetBeans IDE, see the [[Using and configuring NetBeans]] page.

== Comments and Javadoc ==

There are a number of comments in the code below, primarily added as an explanation of the code, but also added as an illustration of comments and how Javadoc can be seen in the NetBeans IDE.


= NetBeans Project =
= NetBeans Project =
Line 13: Line 17:
== Adding the Marauroa library ==
== Adding the Marauroa library ==


Choose the correct way depending on if you are using the marauroa.jar file, of have created a marauroa project from the source code.
Choose the correct way depending on if you are using the marauroa.jar file, or have created a marauroa project from the source code.


=== Using the Jar file ===
=== Using the Jar file ===
Line 19: Line 23:
Use this option unless you need to use the other methods.
Use this option unless you need to use the other methods.


Find the '''marauroa.jar''' file from the download, and copy it to the libs directory (created above) if it is not there already. Right click the '''Libraries''' branch of the server Project tree, and select '''Add Jar/Folder'''. Browse to the the libs directory for this project and select the marauroa.jar file. This will include the marauroa library with no view of the source code.
Find the '''marauroa.jar''' file from the download, and copy it to the libs directory (created above) if it is not there already. Right click the '''Libraries''' branch of the client Project tree, and select '''Add Jar/Folder'''. Browse to the the libs directory for this project and select the marauroa.jar file. This will include the marauroa library with no view of the source code.


=== Using the marauroa project ===
=== Using the marauroa project ===


Right click the '''Libraries''' branch of the server Project tree, and select '''Add Project'''. Make sure you browse to the correct file location and select the '''marauroa''' project that you created earlier. This will include your marauroa library that you built, and you can see the source code.
Right click the '''Libraries''' branch of the client Project tree, and select '''Add Project'''. Make sure you browse to the correct file location and select the '''marauroa''' project that you created earlier. This will include your marauroa library that you built, and you can see the source code.


= Client Files =
= Additional files =


The following files need to be created, as they are not present in the marauroa source file.
The following files are required to extend the Marauroa engine functionality.


=== Client.java ===
== Test.java ==

This file was created when you created the new Project. Add the following (or replace the existing) code. This is the a simple flow to test the client and server code works to give basic communication. Some simple comments are included.

<source lang="Java">
/*
* Test class for Marauroa Chat Tutorial
* - see http://stendhalgame.org/wiki/Marauroa_Chat_Tutorial
*/

package client;

import marauroa.common.Log4J;
import marauroa.common.game.RPObject;

/**
* Run the client to communicate with the server
*/
public class Test {
@SuppressWarnings("SleepWhileInLoop")

private static marauroa.common.Logger logger = Log4J.getLogger(Test.class);

public static void main(String[] args) {

// flag: false to stop client
boolean cond = true;

// create the Client to handle communications
Client my = Client.get();

try {
my.connect("localhost", 5555);

// create new account if 3rd parameter is present (email address)
if (args.length == 3) {
my.createAccount(args[0], args[1], args[2]);
}

// do log in
my.login(args[0], args[1]);
if (my.getAvailableCharacters().length == 0) {
RPObject character = new RPObject();
my.createCharacter(args[0], character);
}
my.chooseCharacter(args[0]);
} catch (Exception e) {
cond = false;
logger.info("Login failure: " + e);
}

// connection loop (no user interaction)
int i = 0;
while (cond) {
++i;

// get and apply messages
my.loop(0);

if (i % 100 == 50) {
my.sendMessage("test" + i);
}

String s = my.popQuote();
while (s != null) {
System.out.println(s);
s = my.popQuote();
}

try {
Thread.sleep(100);
} catch (InterruptedException e) {
cond = false;
}
}
}
}
</source>

Close and Save the file. Note how NetBeans shows an error because it does not recognise the Client class.

== Adding Logging to the Client ==

To trace errors, or to monitor which parts of a program are executed, message (log) statements can be inserted in the code, as in Test.java (above). The log4j library provides a flexible and configurable way to do this. See [[Logging in Marauroa | how this is done]] in Marauroa.

=== The logging configuration file ===

To specify the logging output right-click on the '''client''' package and add a new '''Empty File'''. Give the '''File Name''' as '''log4j_client.properties'''. Add the following lines to that file:

<pre>
# Set root logging level to INFO, and create two output configurations
log4j.rootLogger=INFO, Console, File

# Paste all log entries to the console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d{ISO8601} [%t] %-5p %c - %m%n

# Paste all log entries to a daily log file
log4j.appender.File=org.apache.log4j.DailyRollingFileAppender
log4j.appender.File.File=log/client.log
log4j.appender.File.layout=org.apache.log4j.PatternLayout
log4j.appender.File.layout.ConversionPattern=%d{ISO8601} [%t] %-5p %c - %m%n

# Set priority to warning messages and above, disabling debug and info messages
log4j.logger.marauroa.client=WARN

</pre>

Close and Save the file.

== Adding the log4j library ==

Although this does not create a compile error it will create an error when you run the Text Client.

Copy the '''log4j.jar''' file from the downloaded source files to the '''libs''' directory (created above). Right click the '''Libraries''' branch of the server Project tree, and select '''Add Jar/Folder'''. Browse to the the libs directory for this project and select the log4j.jar file.

== Client.java ==

This file extends the Marauroa ClientFramework class, to provide methods that give the required responses when these actions are carried out.


Right-click on the '''client''' package and add a new '''Java Class'''. Give the '''Class Name''' as '''Client'''. Replace the template code with the following code:
Right-click on the '''client''' package and add a new '''Java Class'''. Give the '''Class Name''' as '''Client'''. Replace the template code with the following code:
Line 35: Line 158:
<source lang="Java">
<source lang="Java">
/*
/*
* Client class for Marauroa Chat Tutorial
*
* - see http://stendhalgame.org/wiki/Marauroa_Chat_Tutorial
*/
*/


Line 54: Line 178:


/**
/**
* Handle the connection to the game Server
*
*/
*/
public class Client extends ClientFramework {
public class Client extends ClientFramework {
private PerceptionHandler handler;
protected static Client client;
private Map<RPObject.ID, RPObject> world_objects;
private String[] available_characters;
private List<String> quotes = new ArrayList<String>();
private static marauroa.common.Logger logger = Log4J.getLogger(Client.class);


public static Client get() {
protected static Client client;
if (client == null) {
client = new Client();
}
return client;
}


private String[] available_characters;
protected Client() {
super("client/log4j_client.properties");
world_objects = new HashMap<RPObject.ID, RPObject>();
handler = new PerceptionHandler(new PerceptionListener());
}


private PerceptionHandler handler;
public String[] GetAvailableCharacters() {
return available_characters;
}


private static marauroa.common.Logger logger = Log4J.getLogger(Client.class);
String popQuote() {
if (quotes.isEmpty()) {
return null;
}
String result = quotes.get(0);
quotes.remove(0);
return result;
}


private List<String> quotes = new ArrayList<String>();
public void SendMessage(String text) {
RPAction action;
action = new RPAction();
action.put("type", "chat");
action.put("text", text);
send(action);
}


private Map<RPObject.ID, RPObject> world_objects;
@Override

protected void onPerception(MessageS2CPerception message) {
try {
/**
* singleton constructor - logger, objects and interface handler
handler.apply(message, world_objects);
*/
} catch (java.lang.Exception e) {
protected Client() {
// Something weird happened while applying perception
logger.warn("Applying perception: " + e);
super("client/log4j_client.properties");
world_objects = new HashMap<RPObject.ID, RPObject>();
handler = new PerceptionHandler(new PerceptionListener());
}
}
}


public static Client get() {
@Override
if (client == null) {
protected List<TransferContent> onTransferREQ(List<TransferContent> items) {
client = new Client();
return items;
}
}
return client;
}


public String[] getAvailableCharacters() {
@Override
return available_characters;
protected void onTransfer(List<TransferContent> items) {
}
}


/**
@Override
* take the next message from the queue
protected void onAvailableCharacters(String[] characters) {
*/
available_characters = characters;
public String popQuote() {
}
if (quotes.isEmpty()) {

return null;
@Override
}
protected void onServerInfo(String[] info) {
for (String s : info) {
String result = quotes.get(0);
quotes.add(s);
quotes.remove(0);
return result;
}
}
}


/**
@Override
* send the message (as an action) to the server
protected String getGameName() {
return "Chat";
*/
public void sendMessage(String text) {
}
RPAction action;

action = new RPAction();
@Override
action.put("type", "chat");
protected String getVersionNumber() {
return "0.1";
action.put("text", text);
send(action);
}

@Override
protected void onPreviousLogins(List<String> previousLogins) {
}

class PerceptionListener implements IPerceptionListener {

@Override
public boolean onAdded(RPObject object) {
if (object.has("text")) {
quotes.add("*" + object.get("from") + "* : " + object.get("text"));
}
return false;
}
}


/**
* process message from server
*/
@Override
@Override
protected void onPerception(MessageS2CPerception message) {
public boolean onModifiedAdded(RPObject object, RPObject changes) {
return false;
try {
handler.apply(message, world_objects);
} catch (java.lang.Exception e) {
// Something weird happened while applying perception
logger.warn("Applying perception: " + e);
}
}
}


/**
* request transfer of content from server
*/
@Override
@Override
protected List<TransferContent> onTransferREQ(List<TransferContent> items) {
public boolean onModifiedDeleted(RPObject object, RPObject changes) {
return false;
return items;
}
}


/**
* process received transfer of content from server
*/
@Override
@Override
protected void onTransfer(List<TransferContent> items) {
public boolean onDeleted(RPObject object) {
return false;
}
}


/**
* on receipt of character list from server, save it
*/
@Override
@Override
protected void onAvailableCharacters(String[] characters) {
public boolean onMyRPObject(RPObject added, RPObject deleted) {
available_characters = characters;
return false;
}
}


/**
* on receipt of server info, store in message queue
*/
@Override
@Override
public void onSynced() {
protected void onServerInfo(String[] info) {
for (String s : info) {
quotes.add(s);
}
}
}


/**
* use to check that this client matches the server
*/
@Override
@Override
public void onUnsynced() {
protected String getGameName() {
return "Chat";
}
}


/**
* use to check that this client version matches the server version
*/
@Override
@Override
protected String getVersionNumber() {
public void onException(Exception e, marauroa.common.net.message.MessageS2CPerception perception) {
e.printStackTrace();
return "0.1";
System.exit(-1);
}
}


/**
* previous logins not used
*/
@Override
@Override
protected void onPreviousLogins(List<String> previousLogins) {
public boolean onClear() {
return false;
}
}


/**
public void onPerceptionBegin(byte type, int timestamp) {
* apply perceptions: add, change or delete objects
}
*/
class PerceptionListener implements IPerceptionListener {


/**
public void onPerceptionEnd(byte type, int timestamp) {
* clear world on sync perceptions
}
*/
}
@Override
}
public boolean onClear() {
</source>
return false;
}


/**
Close and Save the file.
* get new messages from server; add to message queue
*/
@Override
public boolean onAdded(RPObject object) {
if (object.has("text")) {
quotes.add("*" + object.get("from") + "* : " + object.get("text"));
}
return false;
}


/**
=== Test.java ===
* server has deleted an object; client does not need to do anything
*/
@Override
public boolean onDeleted(RPObject object) {
return false;
}


/**
This file was created when you created the new Project. Add the following (or replace the existing) code:
* server has modified an object; client does not need to do anything
*/
@Override
public boolean onModifiedAdded(RPObject object, RPObject changes) {
return false;
}


/**
<source lang="Java">
* server has modified an object; client does not need to do anything
/*
*/
*
@Override
*/
public boolean onModifiedDeleted(RPObject object, RPObject changes) {
return false;
}


/**
package client;
* player avatar is to be processed
*/
@Override
public boolean onMyRPObject(RPObject added, RPObject deleted) {
return false;
}


/**
import marauroa.common.game.RPObject;
* client cannot process perception; exit client
*/
@Override
public void onException(Exception e, marauroa.common.net.message.MessageS2CPerception perception) {
logger.warn("Exit on exception: " + e + " : " + perception.toString());
e.printStackTrace();
System.exit(-1);
}


@Override
/**
public void onPerceptionBegin(byte type, int timestamp) {
*
}
*/

public class Test {
@Override
@SuppressWarnings("SleepWhileInLoop")
public static void main(String[] args) {
public void onPerceptionEnd(byte type, int timestamp) {
boolean cond = true;
}

Client my = Client.get();
try {
@Override
public void onSynced() {
my.connect("localhost", 5555);
if (args.length == 3) {
}

my.createAccount(args[0], args[1], args[2]);
}
@Override
public void onUnsynced() {
my.login(args[0], args[1]);
}
if (my.GetAvailableCharacters().length == 0) {
RPObject character = new RPObject();
my.createCharacter(args[0], character);
}
my.chooseCharacter(args[0]);
} catch (Exception e) {
cond = false;
}
}
int i = 0;
while (cond) {
++i;
my.loop(0);
if (i % 100 == 50) {
my.SendMessage("test" + i);
}
String s = my.popQuote();
while (s != null) {
System.out.println(s);
s = my.popQuote();
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
cond = false;
}
}
}
}
}
</source>
</source>
Line 262: Line 393:
Close and Save the file.
Close and Save the file.


== Adding Logging to the Client ==
= Build the Project =

To trace errors, or to monitor what parts of a program are executed, message statements can be inserted in the code. The log4j library provides a flexible and configurable way to do this. See [[Logging in Marauroa how this is done]] in Marauroa.

=== The logging configuration file ===

To specify the logging output right-click on the '''client''' package and add a new '''Empty File'''. Give the '''File Name''' as '''log4j_client.properties'''. Add the following lines to that file:

<pre>
# Set root logger level to INFO, and create two output configurations
log4j.rootLogger=INFO, Console, File

# Paste all log entries to the console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d{ISO8601} [%t] %-5p %c - %m%n

# Paste all log entries to a daily log file
log4j.appender.File=org.apache.log4j.DailyRollingFileAppender
log4j.appender.File.File=log/client.log
log4j.appender.File.layout=org.apache.log4j.PatternLayout
log4j.appender.File.layout.ConversionPattern=%d{ISO8601} [%t] %-5p %c - %m%n

# Disabled debug messages... to avoid too many logs

</pre>

Close and Save the file.

=== Adding the log4j library ===

Although this does not create a compile error it will create an error when you run the Text Client.

Copy the '''log4j.jar''' file from the downloaded source files to the '''libs''' directory (created above). Right click the '''Libraries''' branch of the server Project tree, and select '''Add Jar/Folder'''. Browse to the the libs directory for this project and select the log4j.jar file.

== Build the Project ==


Finally, select '''Run''', '''Build Main Project''' from the NetBeans menu bar. This will create '''client.jar''' in the '''dist''' directory, and copy the jar files from the libs directory to the '''lib''' sub-directory of dist.
Finally, select '''Run''', '''Build Main Project''' from the NetBeans menu bar. This will create '''client.jar''' in the '''dist''' directory, and copy the jar files from the libs directory to the '''lib''' sub-directory of dist.


== Completion ==
= Completion =


You have created the two class files and compiled them into a java library. Now you can follow the [[Chat Tutorial in NetBeans/Deploy Text Client|deployment instructions]] for preparing and testing your game.
You have created the two class files and compiled them into a java library. Now you should create the [[Chat Tutorial in NetBeans/Server|server files]], then you can follow the [[Chat Tutorial in NetBeans/Deploy Text Client|deployment instructions]] for preparing and testing your code.


[[Category:NetBeans]]
[[Category:NetBeans]]

Latest revision as of 12:13, 29 April 2012

Introduction

From the Design Objectives given in the Chat Tutorial, this is a text based client that runs in a command / terminal window. It is executed on the Server and establishes communications to the Server program, with no user interaction. It includes some error logging, comments and Javadoc output.

For more detail in using the NetBeans IDE, see the Using and configuring NetBeans page.

Comments and Javadoc

There are a number of comments in the code below, primarily added as an explanation of the code, but also added as an illustration of comments and how Javadoc can be seen in the NetBeans IDE.

NetBeans Project

In the NetBeans IDE, close all open projects. Click New Project, choose Java and Java Application. Click Next, then give the Project Name as client. Change the Project Location to DEVPATH\DevChat (DEVPATH, see above); the Project Folder is shown as DEVPATH\DevChat\client with DEVPATH being your chosen location. Check that Create Main Class is ticked, and the Main Class is client.Test before clicking Finish.

The empty Project is created in NetBeans. Under the Files tab you will see the directory structure it has also generated; check this using your file explorer.

Adding the Marauroa library

Choose the correct way depending on if you are using the marauroa.jar file, or have created a marauroa project from the source code.

Using the Jar file

Use this option unless you need to use the other methods.

Find the marauroa.jar file from the download, and copy it to the libs directory (created above) if it is not there already. Right click the Libraries branch of the client Project tree, and select Add Jar/Folder. Browse to the the libs directory for this project and select the marauroa.jar file. This will include the marauroa library with no view of the source code.

Using the marauroa project

Right click the Libraries branch of the client Project tree, and select Add Project. Make sure you browse to the correct file location and select the marauroa project that you created earlier. This will include your marauroa library that you built, and you can see the source code.

Additional files

The following files are required to extend the Marauroa engine functionality.

Test.java

This file was created when you created the new Project. Add the following (or replace the existing) code. This is the a simple flow to test the client and server code works to give basic communication. Some simple comments are included.

<source lang="Java"> /*

*  Test class for Marauroa Chat Tutorial
*   - see http://stendhalgame.org/wiki/Marauroa_Chat_Tutorial
*/

package client;

import marauroa.common.Log4J; import marauroa.common.game.RPObject;

/**

*  Run the client to communicate with the server
*/

public class Test {

   @SuppressWarnings("SleepWhileInLoop")
   private static marauroa.common.Logger logger = Log4J.getLogger(Test.class);
   public static void main(String[] args) {
       // flag: false to stop client
       boolean cond = true;
       // create the Client to handle communications
       Client my = Client.get();
       try {
           my.connect("localhost", 5555);
           // create new account if 3rd parameter is present (email address)
           if (args.length == 3) {
               my.createAccount(args[0], args[1], args[2]);
           }
           // do log in
           my.login(args[0], args[1]);
           if (my.getAvailableCharacters().length == 0) {
               RPObject character = new RPObject();
               my.createCharacter(args[0], character);
           }
           my.chooseCharacter(args[0]);
       } catch (Exception e) {
           cond = false;
           logger.info("Login failure: " + e);
       }
       // connection loop (no user interaction)
       int i = 0;
       while (cond) {
           ++i;
           // get and apply messages
           my.loop(0);
           if (i % 100 == 50) {
               my.sendMessage("test" + i);
           }
           String s = my.popQuote();
           while (s != null) {
               System.out.println(s);
               s = my.popQuote();
           }
           try {
               Thread.sleep(100);
           } catch (InterruptedException e) {
               cond = false;
           }
       }
   }

} </source>

Close and Save the file. Note how NetBeans shows an error because it does not recognise the Client class.

Adding Logging to the Client

To trace errors, or to monitor which parts of a program are executed, message (log) statements can be inserted in the code, as in Test.java (above). The log4j library provides a flexible and configurable way to do this. See how this is done in Marauroa.

The logging configuration file

To specify the logging output right-click on the client package and add a new Empty File. Give the File Name as log4j_client.properties. Add the following lines to that file:

# Set root logging level to INFO, and create two output configurations
log4j.rootLogger=INFO, Console, File

# Paste all log entries to the console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d{ISO8601} [%t] %-5p %c - %m%n

# Paste all log entries to a daily log file
log4j.appender.File=org.apache.log4j.DailyRollingFileAppender
log4j.appender.File.File=log/client.log
log4j.appender.File.layout=org.apache.log4j.PatternLayout
log4j.appender.File.layout.ConversionPattern=%d{ISO8601} [%t] %-5p %c - %m%n

# Set priority to warning messages and above, disabling debug and info messages
log4j.logger.marauroa.client=WARN

Close and Save the file.

Adding the log4j library

Although this does not create a compile error it will create an error when you run the Text Client.

Copy the log4j.jar file from the downloaded source files to the libs directory (created above). Right click the Libraries branch of the server Project tree, and select Add Jar/Folder. Browse to the the libs directory for this project and select the log4j.jar file.

Client.java

This file extends the Marauroa ClientFramework class, to provide methods that give the required responses when these actions are carried out.

Right-click on the client package and add a new Java Class. Give the Class Name as Client. Replace the template code with the following code:

<source lang="Java"> /*

*  Client class for Marauroa Chat Tutorial
*   - see http://stendhalgame.org/wiki/Marauroa_Chat_Tutorial
*/

package client;

import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import marauroa.client.ClientFramework; import marauroa.client.net.IPerceptionListener; import marauroa.client.net.PerceptionHandler; import marauroa.common.Log4J; import marauroa.common.game.RPAction; import marauroa.common.game.RPObject; import marauroa.common.net.message.MessageS2CPerception; import marauroa.common.net.message.TransferContent;

/**

* Handle the connection to the game Server
*/

public class Client extends ClientFramework {

   protected static Client client;
   private String[] available_characters;
   private PerceptionHandler handler;
   private static marauroa.common.Logger logger = Log4J.getLogger(Client.class);
   private List<String> quotes = new ArrayList<String>();
   private Map<RPObject.ID, RPObject> world_objects;
   /**
    *  singleton constructor - logger, objects and interface handler
    */
   protected Client() {
       super("client/log4j_client.properties");
       world_objects = new HashMap<RPObject.ID, RPObject>();
       handler = new PerceptionHandler(new PerceptionListener());
   }
   public static Client get() {
       if (client == null) {
           client = new Client();
       }
       return client;
   }
   public String[] getAvailableCharacters() {
       return available_characters;
   }
   /**
    *  take the next message from the queue
    */
   public String popQuote() {
       if (quotes.isEmpty()) {
           return null;
       }
       String result = quotes.get(0);
       quotes.remove(0);
       return result;
   }
   /**
    *  send the message (as an action) to the server
    */
   public void sendMessage(String text) {
       RPAction action;
       action = new RPAction();
       action.put("type", "chat");
       action.put("text", text);
       send(action);
   }
   /**
    *  process message from server
    */
   @Override
   protected void onPerception(MessageS2CPerception message) {
       try {
           handler.apply(message, world_objects);
       } catch (java.lang.Exception e) {
           // Something weird happened while applying perception
           logger.warn("Applying perception: " + e);
       }
   }
   /**
    *  request transfer of content from server
    */
   @Override
   protected List<TransferContent> onTransferREQ(List<TransferContent> items) {
       return items;
   }
   /**
    *  process received transfer of content from server
    */
   @Override
   protected void onTransfer(List<TransferContent> items) {
   }
   /**
    *  on receipt of character list from server, save it
    */
   @Override
   protected void onAvailableCharacters(String[] characters) {
       available_characters = characters;
   }
   /**
    *  on receipt of server info, store in message queue
    */
   @Override
   protected void onServerInfo(String[] info) {
       for (String s : info) {
           quotes.add(s);
       }
   }
   /**
    *  use to check that this client matches the server
    */
   @Override
   protected String getGameName() {
       return "Chat";
   }
   /**
    *  use to check that this client version matches the server version
    */
   @Override
   protected String getVersionNumber() {
       return "0.1";
   }
   /**
    *  previous logins not used
    */
   @Override
   protected void onPreviousLogins(List<String> previousLogins) {
   }
   /**
    *  apply perceptions: add, change or delete objects
    */
   class PerceptionListener implements IPerceptionListener {
       /**
        *  clear world on sync perceptions
        */
       @Override
       public boolean onClear() {
           return false;
       }
       /**
        *  get new messages from server; add to message queue
        */
       @Override
       public boolean onAdded(RPObject object) {
           if (object.has("text")) {
               quotes.add("*" + object.get("from") + "* : " + object.get("text"));
           }
           return false;
       }
       /**
        *  server has deleted an object; client does not need to do anything
        */
       @Override
       public boolean onDeleted(RPObject object) {
           return false;
       }
       /**
        *  server has modified an object; client does not need to do anything
        */
       @Override
       public boolean onModifiedAdded(RPObject object, RPObject changes) {
           return false;
       }
       /**
        *  server has modified an object; client does not need to do anything
        */
       @Override
       public boolean onModifiedDeleted(RPObject object, RPObject changes) {
           return false;
       }
       /**
        *  player avatar is to be processed
        */
       @Override
       public boolean onMyRPObject(RPObject added, RPObject deleted) {
           return false;
       }
       /**
        *  client cannot process perception; exit client
        */
       @Override
       public void onException(Exception e, marauroa.common.net.message.MessageS2CPerception perception) {
           logger.warn("Exit on exception: " + e + " : " + perception.toString());
           e.printStackTrace();
           System.exit(-1);
       }
       @Override
       public void onPerceptionBegin(byte type, int timestamp) {
       }
       @Override
       public void onPerceptionEnd(byte type, int timestamp) {
       }
       @Override
       public void onSynced() {
       }
       @Override
       public void onUnsynced() {
       }
   }

} </source>

Close and Save the file.

Build the Project

Finally, select Run, Build Main Project from the NetBeans menu bar. This will create client.jar in the dist directory, and copy the jar files from the libs directory to the lib sub-directory of dist.

Completion

You have created the two class files and compiled them into a java library. Now you should create the server files, then you can follow the deployment instructions for preparing and testing your code.