Marauroa Core API: Difference between revisions
Jump to navigation
Jump to search
Content deleted Content added
No edit summary |
imported>Blacklads Undo revision 11663 by Ufizavipupu (Talk) |
||
| (187 intermediate revisions by 6 users not shown) | |||
| Line 1: | Line 1: | ||
{{Navigation for Marauroa Top|Using}} |
|||
Marauroa exposed a very simpled and reduce API in order for you to develop your own games. |
|||
{{Navigation for Marauroa Users}} |
|||
Marauroa exposes a very simplified and reduced API so you can easily develop your own games. A nightly build [http://stendhalgame.org/hudson/job/marauroa_HEAD/javadoc/ JavaDoc API Documentation] is available, too. |
|||
== Content == |
|||
[[Image:Classdiagram_marauroa.common.game_rp_stubs.png|thumb|Class Diagram of RP* classes]] |
|||
!!!Content |
|||
The main entities you should know about are: |
The main entities you should know about are: |
||
* Attributes |
* Attributes |
||
| Line 8: | Line 14: | ||
* RPSlot |
* RPSlot |
||
* RPClass |
* RPClass |
||
If you plan to use Java only also you should know: |
|||
* IRPZone interface |
* IRPZone interface |
||
* IRPRuleProcessor interface |
* IRPRuleProcessor interface |
||
* RPWorld |
|||
To read about these elements please see [[RolePlayingDesign]] and [[GameDesign]]. |
|||
Or if you prefer Python for developing the rules: |
Or if you would prefer to use Python for developing the game rules read about: |
||
* ~PythonZone |
|||
* PythonRP |
* PythonRP |
||
* PythonWorld |
|||
The Python API can be found at [[PyArianneAPIDefinition]] and an example of its use at [[PyArianneAPIExample]]. You can read more about using Python for developing in our game tutorial [[HowToWriteGamesUsingArianne]]. Please note that Python support is dormant. |
|||
!! Attributes |
|||
Attributes are a list of pairs name, value that store information in Arianne. |
|||
The methods exposed by Attributes class are: |
|||
Sets the value of an attribute |
|||
* void put(String name, String value) |
|||
* void put(String name, int value) |
|||
Add quantity to the value of an attribute that MUST exists |
|||
* void add(String name, int quantity) |
|||
== Attributes == |
|||
Returns the value of an attribute |
|||
Attributes are pairs of data stored in a list. Each attribute comprises of a ''name'' and ''value'' element. Attributes are the standard way of storing data in Arianne. An example of an attribute is your age, e.g. name="age" and value=21 |
|||
* String get(String name) |
|||
* int get(String name) |
|||
Each attribute also has a type associated with it that is defined in a ''RPClass''. An attributes is an instance of a ''RPClass'' (see next section of this document to read more on RPClass. |
|||
Removes an entry of the list of attributes |
|||
* void remove(String name) |
|||
There are two special entries in attributes: |
|||
Returns True if an attribute exists |
|||
* ''type'': defines the name of the RPClass that the object belongs to. |
|||
* boolean has(String name) |
|||
* ''id'': defines a unique identifier |
|||
The methods exposed by the Attributes class to the game developer are shown below. These are the functions you should use to modify your attributes. |
|||
Each attribute has its type that is define in a RPClass. An attributes is an instance of a RPClass. |
|||
There are two special entries at attributes: |
|||
* type that define the name of the RPClass the object belong to. |
|||
* id that define an unique |
|||
Setting the value of an attribute: |
|||
_Example_: %%% |
|||
<source lang="java"> |
|||
<verbatim> |
|||
public void put(String name, String value) |
|||
Attributes test=new Attributes(); |
|||
public void put(String name, int value) |
|||
</source> |
|||
test.put("hp",100); |
|||
Add a quantity to the value element of an attribute that MUST already exist: |
|||
if(test.has("hp")) |
|||
<source lang="java"> |
|||
{ |
|||
public void add(String name, int quantity) |
|||
</source> |
|||
Returns the value of an attribute: |
|||
<source lang="java"> |
|||
public String get(String name) |
|||
public int get(String name) |
|||
</source> |
|||
Removes an attribute entry from the list of attributes: |
|||
<source lang="java"> |
|||
public void remove(String name) |
|||
</source> |
|||
Returns True if an attribute exists: |
|||
<source lang="java"> |
|||
public boolean has(String name) |
|||
</source> |
|||
'''Example''': <br> |
|||
<source lang="java"> |
|||
Attributes test=new Attributes(); |
|||
test.put("name","Test attribute"); |
|||
test.put("hp",100); |
|||
if(test.has("hp")) { |
|||
test.add("hp",10); |
|||
} |
} |
||
test.remove("name"); |
test.remove("name"); |
||
</ |
</source> |
||
== RPClass == |
|||
This class is a key concept |
This class is a key concept of Arianne. An RPClass is much like a Java Class but for Arianne RPObjects: it defines the type (string, int, boolean, ...) and the visibility (hidden, private or visible) of the attributes that make up an object (an object is a collection of attributes, for example for a human, age, height etc). |
||
RPClass has five different parts: |
|||
Type Data definition: |
|||
* String a string of up to 2^32 bytes |
|||
* Short String a string of 255 bytes |
|||
* Integer a 32 bits integer |
|||
* Short a 16 bits integer |
|||
* Byte a 8 bits integer |
|||
* Flag a binary flag. |
|||
RPClass is made up of five different parts: |
|||
Visibility Data definition: |
|||
* Visible if the attribute can be seen by clients. |
|||
* Hidden if the attribute is not visible by clients. |
|||
A data type definition: |
|||
Creation of the RPClass: |
|||
* |
* ''String'': a string of up to 2^32 bytes |
||
* |
* ''Short String'': a string of 255 bytes |
||
* ''Integer'': a 32 bits integer |
|||
* void isA(String parent) |
|||
* ''Short'': a 16 bits integer |
|||
* void isA(RPClass parent) |
|||
* ''Byte'': a 8 bits integer |
|||
These methods adds attributes to the RPClass and set the parent of this class. Of course a class can have no parent. |
|||
* ''Flag'': a binary flag. |
|||
The Visibility of the data: |
|||
Query: |
|||
* ''Visible'': if the attribute can be seen by clients. |
|||
* String getName() |
|||
* ''Hidden'': if the attribute is not visible to clients. |
|||
* byte getType(String name) |
|||
* ''Private'': if the attribute is only visible to the client the object is associated with (the player object controlled by this client) |
|||
* byte getVisibility(String name) |
|||
* boolean hasAttribute(String name) |
|||
* boolean subclassOf(String parentclass) |
|||
Once the class is filled with data, you can querey using these methods to get the class name of the class, the the type of an attribute, determine if an attribute exists and to know if that RPClass is a subclass of another. |
|||
Creation methods of the RPClass: (These are part of each RPClass instance, see example below for usage) |
|||
Class wide query: |
|||
<source lang="java"> |
|||
* boolean hasRPClass(String name) |
|||
public void add(String name, byte type) |
|||
public void add(String name, byte type, byte visibility) |
|||
You can query the system classes using these methods, it is not a good idea to modify them once you are running. The class definitions are send to client on connect, if you change class definitions on the middle of a game it is prone that you will crash your clients. |
|||
public void isA(String parent) |
|||
public void isA(RPClass parent) |
|||
</source> |
|||
These methods add attributes to the RPClass and set their type and visibility. You can also set the parent of this class. Of course classes without parents are possible, too. |
|||
When writting a class definition you can skip id and type attributes as they are automatically determined by RPClass. |
|||
Once the class has been filled, you can query the data using these methods. These methods allow you to get the class name of the class, the the type of an attribute, determine if an attribute exists and to know if that RPClass is a subclass of another. |
|||
_Example_: %%% |
|||
<verbatim> |
|||
RPClass objclass=new RPClass("position"); |
|||
objclass.add("x",RPClass.BYTE); |
|||
objclass.add("y",RPClass.BYTE); |
|||
'''Query''': |
|||
objclass=RPClass("player"); |
|||
<source lang="java"> |
|||
objclass.isA("position"); |
|||
public String getName() |
|||
objclass.add("name",RPClass.SHORT_STRING); |
|||
public byte getType(String name) |
|||
objclass.add("dir",RPClass.SHORT_STRING); |
|||
public byte getVisibility(String name) |
|||
objclass.add("score",RPClass.INT); |
|||
public boolean hasAttribute(String name) |
|||
objclass.add("super",RPClass.BYTE); |
|||
public boolean subclassOf(String parentclass) |
|||
objclass.add("!vdir",RPClass.STRING,RPClass.HIDDEN); |
|||
</source> |
|||
objclass.add("!hdir",RPClass.STRING,RPClass.HIDDEN); |
|||
objclass.add("?kill",RPClass.FLAG); |
|||
</verbatim> |
|||
You can query the system classes using these methods. Note that it is '''not''' a good idea to modify them once you are running. The class definitions are send to the client on connect hence if you change the class definitions in the middle of a game you will crash your clients! |
|||
Each time you create a new RPClass and as long as you give it a name ( ie: player, position, ... ) it will be added to the system list of classes. |
|||
Notice on the example the HIDDEN attribute, by default an attribute is visible. |
|||
You can choose not to use RPClasses on your application but the performance penalty will be big both on bandwidth and CPU usage. |
|||
'''Class wide query''': |
|||
!! RPAction |
|||
<source lang="java"> |
|||
It is a object to represent actions that player wants to do. |
|||
boolean hasRPClass(String name) |
|||
It is up to your game about how to define the content ( you should also define a RPClass for these ). |
|||
RPClass getRPClass(String name) |
|||
</source> |
|||
!! RPObject and RPSlot |
|||
An RPObject is the containter of data in Arianne. An RPObject _isa_ Attributes with a list of RPSlots. Think about RPSlots as backpacks, pockets, boxes, ... |
|||
The new methods are: |
|||
* void addSlot(RPSlot slot) |
|||
* RPSlot getSlot(String name) |
|||
* void removeSlot(String name) |
|||
* boolean hasSlot(String name) |
|||
* Iterator slotIterator() |
|||
These methods adds a slot to the object, retrieve it, remove it and test if the slot exists. Finally the slot iterator is used to visit all the slots in the object. |
|||
When writting a class definition you can skip the ''id'' and ''type'' attributes as they are automatically determined by RPClass. |
|||
* RPObject.ID getID() |
|||
This is a helper method to get the ID of the object. |
|||
'''Example''':<br> |
|||
RPSlot has also a very simple API: |
|||
<source lang="java"> |
|||
* void add(RPObject object) |
|||
* RPObject get(RPObject.ID id) |
|||
// a general entity with a position |
|||
* boolean has(RPObject.ID id) |
|||
RPClass objclass = new RPClass("entity"); |
|||
* RPObject remove(RPObject.ID id) |
|||
objclass.add("x", RPClass.BYTE); |
|||
* void clear() |
|||
objclass.add("y", RPClass.BYTE); |
|||
The clear removes all the object of the slot. |
|||
// an entity specialized in players |
|||
objclass = RPClass("player"); |
|||
objclass.isA("entity"); |
|||
objclass.add("name", RPClass.SHORT_STRING); |
|||
objclass.add("direction", RPClass.SHORT_STRING); |
|||
objclass.add("score", RPClass.INT); |
|||
objclass.add("super", RPClass.BYTE); |
|||
objclass.add("!vdir", RPClass.STRING,RPClass.HIDDEN); |
|||
objclass.add("!hdir", RPClass.STRING,RPClass.HIDDEN); |
|||
objclass.add("?kill", RPClass.FLAG); |
|||
</source> |
|||
Each time you create a new RPClass, as long as you give it a name (ie: entity, player, ... ), it will be added to the system list of classes. |
|||
Notice in the example that the hidden attribute must be specified if you want the RPClass to have this property otherwise by default an attribute is visible. |
|||
Note: You can choose not to use RPClasses in your application but that increases network bandwidth usage. |
|||
== RPAction == |
|||
RPAction is an object used to represent actions that a player wants to do. |
|||
It is up to you to create these when you design your game as they are specific to each game ( you should also define a RPClass for these ). |
|||
== RPObject and RPSlot == |
|||
RPObjects are the containters of data in Arianne. An RPObject is an Attributes element with a list of RPSlots attached. |
|||
RPSlots are slots owned by an RPObject into which other RPObjects can be placed (like items in a backpack) |
|||
The methods of the RPObject to modify slots are: |
|||
<source lang="java"> |
|||
public void addSlot(RPSlot slot) |
|||
public RPSlot getSlot(String name) |
|||
public void removeSlot(String name) |
|||
public boolean hasSlot(String name) |
|||
public Iterator slotIterator() |
|||
</source> |
|||
The above methods are used to add a slot to the object, retrieve it, remove it and test if the slot exists. Finally the slot iterator is used to visit all the slots in the object. |
|||
<source lang="java"> |
|||
public RPObject.ID getID() |
|||
</source> |
|||
This is a helper method to get the unique ID of the object. |
|||
RPSlot has a simple API: |
|||
<source lang="java"> |
|||
public void add(RPObject object) |
|||
public RPObject get(RPObject.ID id) |
|||
public boolean has(RPObject.ID id) |
|||
public RPObject remove(RPObject.ID id) |
|||
public void clear() |
|||
</source> |
|||
These methods modify objects in the RPSlot. The clear() method removes all the objects in the slot. |
|||
<source lang="java"> |
|||
public Iterator iterator() |
|||
</source> |
|||
* Iterator iterator() |
|||
It is used to visit all the objects of the slot. |
It is used to visit all the objects of the slot. |
||
<source lang="java"> |
|||
<verbatim> |
|||
// create an object of RPClass player and set some attribute values |
|||
object |
RPObject object = new RPObject("player"); |
||
object.put(" |
object.put("name", "example"); |
||
object.put("score", 0); |
|||
// create a slot called backpack |
|||
RPSlot slot = new RPSlot("backpack"); |
|||
coin.put("type","coin"); |
|||
slot.add(coin); |
|||
object.addSlot(slot); |
object.addSlot(slot); |
||
</verbatim> |
|||
// create an object of RPClass "coin" and put it into the slot |
|||
Now the complex part, where all the nuts are: IRPZone and IRPRuleProcessor interfaces |
|||
RPObject coin = new RPObject("coin"); |
|||
slot.add(coin); |
|||
</source> |
|||
Now for the complex part. Where it all becomes a little nuts!: IRPZone and IRPRuleProcessor interfaces |
|||
==RPWorld== |
|||
This class is just a container of zones. |
|||
RPWorld provides several methods to make easier the handling of RPZones. |
|||
onInit and onFinish are called on server startup and finalization. You need to subclass RPWorld to give proper behaviour to them. |
|||
<source lang="java"> |
|||
public void onInit() throws Exception |
|||
public void onFinish() throws Exception |
|||
</source> |
|||
Some helper methods to add zones and iterate them. |
|||
<source lang="java"> |
|||
public void addRPZone(IRPZone zone) |
|||
public IRPZone getRPZone(IRPZone.ID zoneid) |
|||
public IRPZone getRPZone(RPObject.ID objectid) |
|||
public Iterator<IRPZone> iterator() |
|||
public int size() |
|||
</source> |
|||
Methods to add, get, test existence, remove and modify objects. modify() is as you know for delta^2 algorithm. |
|||
<source lang="java"> |
|||
public void add(RPObject object) throws NoRPZoneException, RPObjectInvalidException |
|||
public RPObject get(RPObject.ID id) throws NoRPZoneException, RPObjectInvalidException |
|||
public boolean has(RPObject.ID id) throws NoRPZoneException, RPObjectInvalidException |
|||
public RPObject remove(RPObject.ID id) throws NoRPZoneException, RPObjectNotFoundException |
|||
public void modify(RPObject object) throws NoRPZoneException |
|||
</source> |
|||
These are helper methods for changing the zone of an object. Use them instead of doing it by hand. |
|||
<source lang="java"> |
|||
public void changeZone(IRPZone.ID oldzoneid, IRPZone.ID newzoneid, RPObject object) throws NoRPZoneException |
|||
public void changeZone(String oldzone, String newzone, RPObject object) throws NoRPZoneException |
|||
</source> |
|||
==IRPZone== |
|||
IRPZone is the interface that handles the world content and the perceptions. In most cases you should use the implementation MarauroaRPZone and extend it. |
|||
!! IRPZone |
|||
This is the class that handle the world content and the perceptions. It would be wise to forget about it, or extend MarauroaRPZone instead as it is a really complex and bug prone class. |
|||
The methods are: |
The methods are: |
||
<source lang="java"> |
|||
<verbatim> |
|||
/** This method is called when the zone is created to |
/** This method is called when the zone is created to populate it */ |
||
public void onInit() throws Exception; |
public void onInit() throws Exception; |
||
/** This method is called when the server finish to save the content of the zone */ |
/** This method is called when the server finish to save the content of the zone */ |
||
public void onFinish() throws Exception; |
public void onFinish() throws Exception; |
||
| Line 166: | Line 263: | ||
/** This method adds an object to the Zone */ |
/** This method adds an object to the Zone */ |
||
public void add(RPObject object) throws RPObjectInvalidException; |
public void add(RPObject object) throws RPObjectInvalidException; |
||
/** This method tag an object of the Zone as modified */ |
/** This method tag an object of the Zone as modified */ |
||
public void modify(RPObject object) throws RPObjectInvalidException; |
public void modify(RPObject object) throws RPObjectInvalidException; |
||
/** This method removed an object of the Zone and return it.*/ |
/** This method removed an object of the Zone and return it.*/ |
||
public RPObject remove(RPObject.ID id) throws RPObjectNotFoundException; |
public RPObject remove(RPObject.ID id) throws RPObjectNotFoundException; |
||
/** This method returns an object of the Zone */ |
/** This method returns an object of the Zone */ |
||
public RPObject get(RPObject.ID id) throws RPObjectNotFoundException; |
public RPObject get(RPObject.ID id) throws RPObjectNotFoundException; |
||
/** This method returns true if the object exists in the Zone */ |
/** This method returns true if the object exists in the Zone */ |
||
public boolean has(RPObject.ID id); |
public boolean has(RPObject.ID id); |
||
| Line 180: | Line 281: | ||
/** Iterates over the elements of the zone */ |
/** Iterates over the elements of the zone */ |
||
public Iterator iterator(); |
public Iterator iterator(); |
||
/** Returns the number of elements of the zone */ |
/** Returns the number of elements of the zone */ |
||
public long size(); |
public long size(); |
||
| Line 185: | Line 287: | ||
/** This method return the perception of a zone for a player */ |
/** This method return the perception of a zone for a player */ |
||
public Perception getPerception(RPObject.ID id, byte type); |
public Perception getPerception(RPObject.ID id, byte type); |
||
/** This method is called to take zone to the next turn */ |
/** This method is called to take zone to the next turn */ |
||
public void nextTurn(); |
public void nextTurn(); |
||
/** Method to create the map to send to player's client */ |
/** Method to create the map to send to player's client */ |
||
public java.util.List buildMapObjectsList(RPObject.ID id); |
public java.util.List buildMapObjectsList(RPObject.ID id); |
||
</ |
</source> |
||
In most of the cases all you will |
In most of the cases all you will wish to modify are: |
||
* onInit |
* onInit |
||
* onFinish |
* onFinish |
||
* buildMapObjectsList |
* buildMapObjectsList |
||
==IRPRuleProcessor== |
|||
This class must be implemented fully, but it is a childs toy compared to IRPZone :). This is where you code all your games rules.<br> |
|||
!!IRPRuleProcessor |
|||
The API is as follows: |
|||
This class *MUST* be implemented fully, but it is a child toy compared to IRPZone :). Here is where you code all your games rules. |
|||
<source lang="java"> |
|||
The API is as: |
|||
<verbatim> |
|||
/** Set the context where the actions are executed. |
/** Set the context where the actions are executed. |
||
* @param zone The zone where actions happens. */ |
* @param zone The zone where actions happens. */ |
||
public void setContext(IRPZone zone); |
public void setContext(IRPZone zone); |
||
/** Pass the whole list of actions so that it can approve or deny the actions in it. |
/** Pass the whole list of actions so that it can approve or deny the actions in it. |
||
* @param id the id of the object owner of the actions. |
* @param id the id of the object owner of the actions. |
||
* @param actionList the list of actions that the player wants to execute. */ |
* @param actionList the list of actions that the player wants to execute. */ |
||
public void approvedActions(RPObject.ID id, RPActionList actionList); |
public void approvedActions(RPObject.ID id, RPActionList actionList); |
||
/** Execute an action in the name of a player. |
/** Execute an action in the name of a player. |
||
* @param id the id of the object owner of the actions. |
* @param id the id of the object owner of the actions. |
||
| Line 214: | Line 319: | ||
* refer to Actions Explained for more info. */ |
* refer to Actions Explained for more info. */ |
||
public RPAction.Status execute(RPObject.ID id, RPAction action); |
public RPAction.Status execute(RPObject.ID id, RPAction action); |
||
/** Notify it when a new turn happens */ |
/** Notify it when a new turn happens */ |
||
public void nextTurn(); |
public void nextTurn(); |
||
/** Callback method called when a new player enters in the game |
/** Callback method called when a new player enters in the game |
||
* @param object the new player that enters in the game. */ |
* @param object the new player that enters in the game. */ |
||
public boolean onInit(RPObject object) throws RPObjectInvalidException; |
public boolean onInit(RPObject object) throws RPObjectInvalidException; |
||
/** Callback method called when a new player exits the game |
/** Callback method called when a new player exits the game |
||
* @param id the new player id that exits the game. |
* @param id the new player id that exits the game. |
||
* @return true to update the player on database. */ |
* @return true to update the player on database. */ |
||
public boolean onExit(RPObject.ID id) throws RPObjectNotFoundException; |
public boolean onExit(RPObject.ID id) throws RPObjectNotFoundException; |
||
/** Callback method called when a new player time out |
/** Callback method called when a new player time out |
||
* @param id the new player id that timeouts. */ |
* @param id the new player id that timeouts. */ |
||
public boolean onTimeout(RPObject.ID id) throws RPObjectNotFoundException; |
public boolean onTimeout(RPObject.ID id) throws RPObjectNotFoundException; |
||
</ |
</source> |
||
[[Category:Marauroa]] |
|||
!!! Questions |
|||
{{#breadcrumbs: [[Marauroa]] | [[Navigation for Marauroa Users|Using]] | [[Marauroa Core API|Core API]]}} |
|||
Do you have questions? Edit the page and place here. |
|||
Regards, |
|||
Miguel |
|||