AddingArrivalEventMessages.html
13nov10 CmdrZin
25nov10

Adding Arrival Event Messages to Support Avatars

This mod is to enhance the Message Factory to support an arrival message to be broadcast to all Clients by the Server.
The main idea is to be able to track Players and NPCs in real time on the 3D view.
There already is a mechinism to detect when a MudUser object enters a Room (i.e. is added to the Room's inventory). So, all we have to do is add a task or broadcast message with the MudUser ID or such to tell all the Clients of a change in position.
The Client will update its scene tree to cause the MudUser avatar to show up in the new location by changing the position parameters.

Start with the Door.java::ArrivalTask that is generated when ever something enters a Room.
Should be able to either add a broadcast message to the run() method or generate a new Task to do the broadcast.
To find out what it takes to do a broadcast, we'll look at what happens when a Player enters the Game.

This is the code used when a Player leaves the game:
                Channel bcast = AppContext.getChannelManager().getChannel(MudMain.BROADCAST);
                String message = getName() + " has left the game.\n";
                leaveChannel(bcast);
                ClientSession session = getSession();   // POSSIBLE problem
                ByteBuffer bb = ByteBuffer.wrap(message.getBytes());
                bcast.send(session, bb);

Going back to review UnderstandingDarkMud01.html to get more info on Channels.

Hmm..didn't have
public void receivedMessage(ClientChannel channel, ByteBuffer message)
enabled..maybe??..YUP..that't all it was...too simple...
Change MudClient
    public void receivedMessage(ClientChannel channel, ByteBuffer message) {
//        if (session == null) {
            receivedMessage(message);
//        }
    }
Any Channel messages get resolved as normal messages and end up in handleMessage().
Next up..add a new Message ID for positions called PositionMessage.
Add to Message.java comments and spelling changes. Moved ID list to MessageFactory.java.
Add a new Java class to messages called PositionMessage.java
Copy ExpMessage.java code into PositionMessage.java to get most of the needed methods.
Set PositionMessage ID to 3 and make constructors (see code)
When ever something Arrives at a room, then send the ID (hashcode), the MudObject type, and position (Vector3D).
Will add the name later so the User can mouse over the dot to see who it is or maybe add a floating bubble with the name in it.
Add to PositionMessage.java data area.
    /** The identifier. A unique hash code. */
    private int objectID;

    /** MudObject type to determine what color to give it. */
    private MudObject.MudType objectType;

    /** Objects position. */
    private Vector3f objectPosition;
and add accessor methods and encode/decode methods for messages. (see code)
Add to MudClient.java
import com.sun.sgs.darkmud.messages.PositionMessage;
and add case to handleMessage() for position message
            case PositionMessage.ID: {
                PositionMessage msg = (PositionMessage) message;
                String pStr = "\n" + msg.getObjectId() +
                        " of type:" + msg.getObjectType() +
                        " is at " + msg.getObjectPosition() +
                        "\n";
                appendOutput(pStr, Flag.OUTPUT);
                break;
            }
and lastly, have the Door::ArrivalTask use the new message to send the event information.
//            TextMessage msg = new TextMessage(invoker.getDescription() +
//                    " is a " + invoker.getType() +
//                    " with ID:" + invoker.hashCode() +
//                    " at " + where.getPosition() +
//                    "\n");
            PositionMessage msg = new PositionMessage(invoker.hashCode(),
                    invoker.getType(),where.getPosition());
The MessageFactory makes sending complex messages much easier..
So does it work?...oops..forgot to add the nnew message to the MessageFactory..doh..
Change MessageFactory::getMessage()
            case PositionMessage.ID: {
                message = new PositionMessage();
                break;
            }
try again..woo hoo...works great..next up..the graphics..Green dot, Blue dot, Red dot oh My!