Server Plugins Messages
Sending a Message between Server Plugins
Sending a message between server plugins combines the server part of the two other message systems so we have both sending code and receiving code (also known as a hook) written in the server. Messages between Server Plugins are just as important as they allow events occurring in one area of the server to cause events to occur in other parts of the server. A good example of this is updating a characters stats when they equip an item. The equipping of the item occurs in the Inventory plugin (as it moves the item between inventory bags) and the updating of a characters stats occurs in the Combat plugin. This example will be shown and explained at the bottom of the page.
The instructions are split into two sections: Sending the Message and Receiving the Message.
Sending the Message
1) Create the Message Type
MessageTypes are defined in the AGIS code in the Client.java files found in the plugins package. They are a simple string lookup as shown by this example from VoxelClient.java:
public static final MessageType MSG_TYPE_PLACE_CLAIM_OBJECT = MessageType.intern("voxel.PLACE_CLAIM_OBJECT");
The intern string needs to be unique. You can simply copy an existing MessageType entry and paste it, renaming both the variable name and intern name.
2) Creating the Message
It is recommended (but not required) to make a new Message class for each new message. This allows for adding your own variables and get/set functions to ensure correct data setting and getting. Like the MessageTypes, the Message class is generally created in the Client.java files.
The Class should extend PropertyMessage, public and static:
public static class MyTestMessage extends PropertyMessage {
The constructor needs to call super(oid) and set the MessageType:
public MyTestMessage(OID oid, int someNumber) { super(oid); setMsgType(MSG_TYPE_ALTER_CURRENCY); setSomeNumber(someNumber); }
3) Creating a Message Sending function
To make sending the message easier it is recommended to create a message sending function inside the same Client.java file. The function is just a public static function that creates an instance of the Message and sends it. It will end up looking like:
public static void sendMyTestMessage(OID oid, int someNumber) { MyTestMessage msg = new MyTestMessage(oid, someNumber); Engine.getAgent().sendBroadcast(msg); }
4) Calling the Message Sending function
With a public static function created it is super easy to send your message out. From anywhere in the Java code you can call the function created above.
5) Adding the Message and MessageType to the config scripts
The final step in sending the message is to add the Message class name to worldmarshallers.txt and the MessageType to worldmessages.py. These two files can be found in the config/world folder in the server files. Copy one of the existing examples and rename it to have the right Client and class name.
Since version 10.8.0 you need to add MessageType in the MessageInitializer.java class to work with All In One mode
Receiving the Message
1) Creating the MessageHook class
The MessageHook is the class that will pick up the message and do stuff with it. It needs to convert the msg variable to your Message Class created above, then the subject and any other variables set can be retrieved.
It needs to be created in the *Plugin.java file (replacing the * with the relevant plugin type). The Hook class must implement the Hook interface and have the processMessage() function as shown in the example given below:
class MyTestMessageHook implements Hook { public boolean processMessage(Message msg, int flags) { MyTestMessage testMsg = (MyTestMessage)msg; OID playerOid = testMsg.getSubject(); Log.debug("MSG: got testMessage"); // Get the number property int someNumber = testMsg.getSomeNumber(); ... return true; } }
You can add your own code in the … area.
2) Adding the Message Type to the filter and MessageHook list
At the top of each Plugin class/file there is a MessageFilter and a bunch of Hook registrations. These are needed to tell the plugin to listen for the specified message from the client (or other areas of the server) and then tell it which Hook it should run when it gets the message of that type.
The following needs to be added to the onActivate() function:
getHookManager().addHook(MyClient.MSG_TYPE_MY_TEST_MESSAGE, new MyTestMessageHook());
and a bit further below:
filter.addType(MyClient.MSG_TYPE_MY_TEST_MESSAGE);
You will need to change these to use your new MessageType and MessageHook.
Just to be confusing, sometimes the first bit of code (the addHook) may be in a different function. Search the plugin file you are working with for wherever they are all stored (always near the top of the file).
Example: Sending an Item Equipped Message from the Inventory System to the Combat Plugin
When an item is equipped a message is sent out from the InventoryPlugin class and is caught by the CombatPlugin class. The CombatPlugin then gets the item from the message and updates the characters stats based on the properties of the item.
Part 1) The Message (AgisInventoryClient.java, worldmarshallers.txt, worldmessages.py)
The Message class, Message Type and the sending function are all found in the AgisInventoryClient class. They look like:
Part 2) Sending the Message (AgisInventoryPlugin.java)
The equip() function in the AgisInventoryPlugin class calls the sending function (insert name):
Part 3) Receiving the Message (CombatPlugin.java)
The Hook class is created in the CombatPlugin class and is added in the (function name) function and the filter for the message type is added in the onActivate() function: