Developing TicToe HTML5/Implementing Server Entities: Difference between revisions
Jump to navigation
Jump to search
Content deleted Content added
imported>Hendrik Brummermann No edit summary |
imported>Hendrik Brummermann No edit summary |
||
| (31 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
<noinclude>{{Navigation TicToe HTML5}}</noinclude> |
<noinclude>{{Navigation TicToe HTML5}}__NOTOC__</noinclude> |
||
Now we have a user interface on the client side and an empty server. The server is the place where all the interesting logic will happen. But before we can start coding the game rules, we need to implement the entities. |
Now we have a user interface on the client side and an empty server. The server is the place where all the interesting logic will happen. But before we can start coding the game rules, we need to implement the entities. |
||
| Line 31: | Line 31: | ||
public Entity() { |
public Entity() { |
||
// default constructor |
// default constructor |
||
setRPClass("entity"); |
|||
} |
} |
||
| Line 58: | Line 59: | ||
</source> |
</source> |
||
It is a good design to make the interface of a class explicit. Therefore we define get- and set- |
It is a good design practice to make the interface of a class explicit. Therefore we define get- and set- methods for those attributes: |
||
<source lang="java"> |
<source lang="java"> |
||
| Line 114: | Line 115: | ||
public Gameboard() { |
public Gameboard() { |
||
// default constructor |
// default constructor |
||
setRPClass("gameboard"); |
|||
} |
} |
||
| Line 218: | Line 220: | ||
Again the imports and constructors have been left out. |
Again the imports and constructors have been left out. |
||
== Factory == |
|||
The last step is to make our entities known to Marauroa. Therefore we create a new ObjectFactory implementation called net.sf.arianne.tictoe.server.core.TicToeObjectFactory. While this does the same thing as the object factory on the client side, the syntax is a bit different: |
|||
<source lang="java"> |
|||
package net.sf.arianne.tictoe.server.core; |
|||
import marauroa.common.game.RPClass; |
|||
import marauroa.common.game.RPObject; |
|||
import marauroa.server.game.rp.RPObjectFactory; |
|||
import net.sf.arianne.tictoe.server.entity.Gameboard; |
|||
import net.sf.arianne.tictoe.server.entity.Player; |
|||
import net.sf.arianne.tictoe.server.entity.Token; |
|||
/** |
|||
* Creates concrete objects of entities. |
|||
*/ |
|||
public class TicToeObjectFactory extends RPObjectFactory { |
|||
private static RPObjectFactory singleton; |
|||
/** |
|||
* returns the factory instance (this method is called |
|||
* by Marauroa using reflection). |
|||
* |
|||
* @return RPObjectFactory |
|||
*/ |
|||
public static RPObjectFactory getFactory() { |
|||
if (singleton == null) { |
|||
singleton = new TicToeObjectFactory(); |
|||
} |
|||
return singleton; |
|||
} |
|||
@Override |
|||
public RPObject transform(final RPObject object) { |
|||
final RPClass clazz = object.getRPClass(); |
|||
if (clazz == null) { |
|||
return super.transform(object); |
|||
} |
|||
final String name = clazz.getName(); |
|||
if (name.equals("player")) { |
|||
return new Player(object); |
|||
} else if (name.equals("gameboard")) { |
|||
return new Gameboard(object); |
|||
} else if (name.equals("token")) { |
|||
return new Token(object); |
|||
} |
|||
return super.transform(object); |
|||
} |
|||
} |
|||
</source> |
|||
This is a very simple implementation of the transform method, but as we only have 3 entities, this is okay for now. Complex programs usually replace the if/else-if construct with a registration mechanism. |
|||
This new class has to be added to server.ini: |
|||
<source lang="ini"> |
|||
factory_implementation=net.sf.arianne.tictoe.server.core.TicToeObjectFactory |
|||
</source> |
|||
== Rule Processor == |
|||
The last basic class is the Rule Processor. It will receive all events from Marauroa and act in a game specific manner. We will register it in server.ini as: |
|||
<source lang="ini"> |
|||
ruleprocessor=net.sf.arianne.tictoe.server.core.TicToeRule |
|||
</source> |
|||
It is a singleton class, and therefore has to implement a get-method for the instance: |
|||
<source lang="java"> |
|||
package net.sf.arianne.tictoe.server.core; |
|||
import marauroa.common.game.RPObject; |
|||
import marauroa.server.game.rp.IRPRuleProcessor; |
|||
import marauroa.server.game.rp.RPRuleProcessorImpl; |
|||
import net.sf.arianne.tictoe.server.entity.Entity; |
|||
import net.sf.arianne.tictoe.server.entity.Gameboard; |
|||
import net.sf.arianne.tictoe.server.entity.Player; |
|||
import net.sf.arianne.tictoe.server.entity.Token; |
|||
/** |
|||
* provides the rules of the game. |
|||
*/ |
|||
public class TicToeRule extends RPRuleProcessorImpl { |
|||
private static RPRuleProcessorImpl instance; |
|||
/** |
|||
* gets the Rule singleton object |
|||
* |
|||
* @return Rule |
|||
*/ |
|||
public static IRPRuleProcessor get() { |
|||
if (instance == null) { |
|||
instance = new TicToeRule(); |
|||
} |
|||
return instance; |
|||
} |
|||
</source> |
|||
The constructor of the rule processor is a good place, to define the RPClasses: |
|||
<source lang="java"> |
|||
/** |
|||
* creates the rule processor |
|||
*/ |
|||
public TicToeRule() { |
|||
Entity.generateRPClass(); |
|||
Player.generateRPClass(); |
|||
Gameboard.generateRPClass(); |
|||
Token.generateRPClass(); |
|||
} |
|||
</source> |
|||
We override the method createCharacterObject, to tell Marauroa, that newly created character objects should use the class "Player": |
|||
<source lang="java"> |
|||
/** |
|||
* Creates an new character object that will used by createCharacter |
|||
* |
|||
* @param username the username who owns the account of the character to be added. |
|||
* @param character the character to create |
|||
* @param template the desired values of the avatar representing the character. |
|||
* @return RPObject |
|||
*/ |
|||
@SuppressWarnings("unused") |
|||
@Override |
|||
protected RPObject createCharacterObject(String username, String character, RPObject template) { |
|||
Player player = new Player(); |
|||
player.setPlayerName(character); |
|||
return player; |
|||
} |
|||
} |
|||
</source> |
|||