Using Marauroa-Marauroa Core API
转自https://stendhalgame.org/wiki/Marauroa_Core_API
Marauroa提供了一套非常简单的API,使用它可以很容易开发游戏。
内容
Marauroa Core API主要包括以下内容:
- Attributes
- RPAction
- RPObject
- RPSlot
- RPClass
- IRPZone interface
- IRPRuleProcessor interface
- RPWorld
Attributes
Attributes用于保存属性列表。每一个属性都由属性名(name)和属性值(value)组成。例如对于年龄属性,name="age"、value=21。
每一个属性也与一个type相关联,type由 RPClass 类定义,而属性是RPClass的一个实例。
在属性中有两个特殊的条目:
- type: 定义对象所属的RPClass的名字
- id: 定义一个唯一标识符
Attributes提供给游戏开发者以下方法,用于修改属性。
// 设置属性值
public void put(String name, String value)
public void put(String name, int value)
// 增加属性值(属性必须存在)
public void add(String name, int quantity)
// 返回属性值
public String get(String name)
public int get(String name)
// 删除一个属性条目
public void remove(String name)
// 属性是否存在
public boolean has(String name)
示例
Attributes test=new Attributes();
test.put("name","Test attribute");
test.put("hp",100);
if(test.has("hp")) {
test.add("hp",10);
}
test.remove("name");
RPClass
这是Marauroa中的核心概念。对于RPObjects来说RPClass更像是Java中的Class。对象由属性构成(对象是属性的集合,例如人由年龄属性和身高属性构成),RPClass定义了属性的type(string, int,boolean...)和可见性(hidden, private or visible)。
数据类型定义:
- 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.
数据可见性:
- Visible: 属性对客户端可见
- Hidden: 属性对客户端不可见
- Private: 属性仅对关联的客户端对象可见(被客户端控制的玩家对象)
// 向RPClass增加属性,同时设置类型和可见性
public void add(String name, byte type)
public void add(String name, byte type, byte visibility)
// 设置父类型
public void isA(String parent)
public void isA(RPClass parent)
// Query
public String getName()
public byte getType(String name)
public byte getVisibility(String name)
public boolean hasAttribute(String name)
public boolean subclassOf(String parentclass)
// Class wide query
boolean hasRPClass(String name)
RPClass getRPClass(String name)
注意在运行时改变RPClass定义不是一个好主意,可能会导致客户端崩溃。在定义RPClass时,可以跳过id和type属性,它们由RPClass自动设置。
示例:
// a general entity with a position
RPClass objclass = new RPClass("entity");
objclass.add("x", RPClass.BYTE);
objclass.add("y", RPClass.BYTE);
// 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);
每次创建一个新的RPClass,只要给了它一个名字(例如:entity,player...),它就会被加入到系统class列表中。注意在例子中属性默认时可见的,隐藏的属性必须单独指定。在程序中可以不使用RPClass,但是会增加带宽。
RPAction
RPAction对象用于表示玩家要执行的动作。它是针对不同游戏的(也应该为它们定义RPClass)。
RPObject and RPSlot
在Marauroa中RPObject是数据的容器,是关联RPSlot列表的Attributes。RPSlot是RPObject的插槽,其他RPObject可以放入插槽中(就像背包中的物体一样)。
// RPObject修改插槽的方法
public void addSlot(RPSlot slot)
public RPSlot getSlot(String name)
public void removeSlot(String name)
public boolean hasSlot(String name)
public Iterator slotIterator()
// 获得对象id
public RPObject.ID getID()
// 修改RPSlot中的对象
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()
public Iterator iterator()
// create an object of RPClass player and set some attribute values
RPObject object = new RPObject("player");
object.put("name", "example");
object.put("score", 0);
// create a slot called backpack
RPSlot slot = new RPSlot("backpack");
object.addSlot(slot);
// create an object of RPClass "coin" and put it into the slot
RPObject coin = new RPObject("coin");
slot.add(coin);
RPWorld
该类只是区(IRPZone)的容器,RPWorld提供了几个方法以帮助RPZone的处理。
// 服务器启动和结束时调用
public void onInit() throws Exception
public void onFinish() throws Exception
// 增加和遍历区
public void addRPZone(IRPZone zone)
public IRPZone getRPZone(IRPZone.ID zoneid)
public IRPZone getRPZone(RPObject.ID objectid)
public Iterator<IRPZone> iterator()
public int size()
// 增加、获得、测试存在性、移除和修改对象
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
// 改变对象的区,使用changeZone可以避免手动处理
public void changeZone(IRPZone.ID oldzoneid, IRPZone.ID newzoneid, RPObject object) throws NoRPZoneException
public void changeZone(String oldzone, String newzone, RPObject object) throws NoRPZoneException
IRPZone
IRPZone是处理世界内容和感知的接口,大多数情况下你需要使用MarauroaRPZone实现并扩展它。
/** This method is called when the zone is created to populate it */
public void onInit() throws Exception;
/** This method is called when the server finish to save the content of the zone */
public void onFinish() throws Exception;
/** This method adds an object to the Zone */
public void add(RPObject object) throws RPObjectInvalidException;
/** This method tag an object of the Zone as modified */
public void modify(RPObject object) throws RPObjectInvalidException;
/** This method removed an object of the Zone and return it.*/
public RPObject remove(RPObject.ID id) throws RPObjectNotFoundException;
/** This method returns an object of the Zone */
public RPObject get(RPObject.ID id) throws RPObjectNotFoundException;
/** This method returns true if the object exists in the Zone */
public boolean has(RPObject.ID id);
/** This method create a new RPObject with a valid id */
public RPObject create();
/** Iterates over the elements of the zone */
public Iterator iterator();
/** Returns the number of elements of the zone */
public long size();
/** This method return the perception of a zone for a player */
public Perception getPerception(RPObject.ID id, byte type);
/** This method is called to take zone to the next turn */
public void nextTurn();
/** Method to create the map to send to player's client */
public java.util.List buildMapObjectsList(RPObject.ID id);
大多数情况下你将希望修改下面的方法:
- onInit
- onFinish
- buildMapObjectsList
IRPRuleProcessor
该类必须被完整的实现,但是与IRPZone相比,它就是一个孩子的玩具:)
/** Set the context where the actions are executed.
* @param zone The zone where actions happens. */
public void setContext(IRPZone zone);
/** 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 actionList the list of actions that the player wants to execute. */
public void approvedActions(RPObject.ID id, RPActionList actionList);
/** Execute an action in the name of a player.
* @param id the id of the object owner of the actions.
* @param action the action to execute
* @return the action status, that can be Success, Fail or incomplete, please
* refer to Actions Explained for more info. */
public RPAction.Status execute(RPObject.ID id, RPAction action);
/** Notify it when a new turn happens */
public void nextTurn();
/** Callback method called when a new player enters in the game
* @param object the new player that enters in the game. */
public boolean onInit(RPObject object) throws RPObjectInvalidException;
/** Callback method called when a new player exits the game
* @param id the new player id that exits the game.
* @return true to update the player on database. */
public boolean onExit(RPObject.ID id) throws RPObjectNotFoundException;
/** Callback method called when a new player time out
* @param id the new player id that timeouts. */
public boolean onTimeout(RPObject.ID id) throws RPObjectNotFoundException;