QuestNPCs.html
13oct09 CmdrZin
09feb10

Ref1: C. Horstmann, G. Cornell, 2009, "Core Java: Volume I - Fundamentals", 8th Ed.

Quest NPCs

Respond to the ask <name> command as in "ask joe".
A dialog pop-up is generated for the quest.
Inventory items are checked for quest completion and experience, money, and/or items given.

QuestNPC.java

Start with Zombie class, but remove just about everything. Need to keep the TimedTask object to allow the NPC
to do things autonomously.
Add parse support to recognize "ask" command and cause dialog pop-up.
Could have more than one quest, but not all will be available at once. Need to have MudUser record completed quests
so conditional quests and sequential quests can be created.

On the Client side, a pop up window or frame will be needed. A dialog box may work since the quest acceptance is yes/no.
Check out how the Magic Map works to get its diplay up. This has to be message based, so trace its data flow from Server to Client.  

Client Side for Magic Map Pop Up

MudClient.java->MapDisplay->MapFrame
So, when joinedChannel with ClientChennel equal Mapper.MAP_CHANNEL, a new MapFrame is made and the display generated.
It must be getting call through the ClientChannelListener interface that the mudClient implements. The question is "Do we use
the Channel method or parse it out like the info messages?". The Channel method would be good for some parallel task with
lots of data to be handled outside game play. Maybe it would be good for NPC Merchant and NPC Trainer interaction.
All we need here is a simple dialog opo up, so the normal message system will be tried first.

MudClient.java

Adding another special character token to parse out quest messages. Will use a '[' to mark a quest message.
Change MudClient.receiveMessage
    Transfer to questManager.parse if a '[' is the first charater in the message. (neet new class QuestDisplay)
Testing with a simple Dialog box first..this may be all that's needed..use "info" command to trigger test message
(see MudUser.processInfoCommand)
Add showQuestDialog() to display and return String for answer.
Woo Hoo..works great..and simple too..Love it when a plan comes together..("A-Team" for you youngsters).
Now to come up with some quests..
 

QuestDisplay.java

This class will have all of the support for displaying the Quest Dialog Pop Up and sending the selection back to the Server.
Will make this an extension of JOptionPane since that's what is used for the login operation.
Turns out that this is not needed. The Dialog box works fine and can be used for multiple options also for simple dialogs.
 

QuestNPC.java

Ok, back to this one. Copy Zombie.java and clean it up a bit.
Making a new directory call com.sun.sgs.darkmud.quest to put things inlike the QusetNPC class.
NOTE: Ref WallMap.commitCommand() for responding to the Player leaving the room. Zombie already has
code for ARRIVE.
Need to add parseOuterCommand to respond to "ask". See MudObject(look) and MudCharacter(say & emote)
Code needed since the Zombie class didn't resolve any command, only registered interest and then committed.
Added code to parseOuterCommand() and a command enum for CommandType in the declaration area to the begining
of the class.
  if ((command.getType() == null) &&
      (command.getCommand().startsWith("ask "))) {
      command.setType(QuestNPC.CommandType.ASK);
      command.replaceCommand(command.getCommand().substring(4));
      command.registerInterest(this, null);
 }

Cleaned up and put in some messages..this should work now for greeting Players when they enter and if they stay in the room.
Just need to add to inventory of a room, same as Zombie.
Add to MudMain.properties
item.questNPC001.class=com.sun.sgs.darkmud.quest.QuestNPC
item.questNPC001.aliases=SgtPhilips
item.questNPC001.description=SgtPhilips, the local quartermaster.
and add to OfficeLL5824

and it almost works. The timed response works, but the message on arrival does not..hmm..
Still had the 50% follow active..deleted that and added a sayGoodbye task to trigger on GO..still have to check for that
Player leaving to close the screen, else it would close if anyone left!
Also added an AskTask for the ASK command...don't know if this the way to do this yet.
Well, the ARRiVE task now works, but the ASK doesn't..hmm..got pop up to show by not testing the command for the NPC
name. Seems the alias list is not being generated for the class..hmm..these derived classes have a test on the alias before sending to MudObject to add to the alias list..going to remove for now..hmm..can't, breaks the structure..so making MudObject.addAlias public and calling it after super()..that did it..ASK command works now...woo hoo
Add toLowerCase() to msg string also..capts in name now work..back to fixng up the Client.  

MudClient.java

Add code to send back DialogText..this will change to support different dialog options later. This is the same code that is
used to send user commands entered in the text box, so it should work.
  } else if(message[0] == '[') {
      String qStr = showQuestDialog(msg.substring(1));
      try {
          appendOutput(txtInput.getText(), Flag.INPUT);
          ByteBuffer bb = ByteBuffer.wrap(qStr.getBytes());
          simpleClient.send(bb);
      } catch (IOException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
      }
  } else {
Ok. Looking good here..need to read up on the JOptionPane class to see what other things it can do besides get text.
Chapter 9 [1] has a nice user interface discussion and covers use of the option pane. Looks like  the showOptionDialog()
with icon and radio button select is the way to go..mods to MudClient.java to test it out since it already has a pop-up from earlier tests.
The interaction will be in two stages. The first dialog box will ask "What do you want to talk about?" (this text
may change based on the feeling the NPC has to the player) and a radio button list will be available.
1-I'd like my next assignment.
2-What items are available?
3-I need to know if you have info on something I encountered
4-Any good rumors about this place?
or other similar possible topics. Once a selection is made, the player will be joined to a Channel to handle the rest of the interactions. Using the Channel system allows easier control of the message parsing and doesn't cause further mods to the existing general message parsing system. That's the idea anyway.

MudClient.showQuestDialog() changes
Added the ButtonPanel class (from ch 9 pg 456 [1])
Well, it sort of works..four buttons used to indicate the selection. The buttons can be replaced with components, but they still show up along the bottom so just going to use the butons.
The dialog box is modal though, i.e. output stops while it is open, but the game doesn't. This causes the text box to 'catch up' once the dialog is closed. Be fore warned.
If you "ask phil" then the dialog pops up. Now to work on the Channel system to support the four types of questions. (see ImplimentingChannelsForZMUohmy.html)

Well, seems Channels is not the way to go. So, adding com.sun.sgs.darkmud.messages which is a message module from another game I was doing. It uses the Message Factory concept that I first saw in the sgs-tank demo game and appearantly is a common means of message management. Its operation and use is described in ZMUohMy_MessageFactory.html. This method will be used for all messaging in the game, so time for a major rewrite of Server and Client message operations....wonderful.

18dec09
Well, that took a bit longer than expected, but the MessageFactory system is in place to send messages from the Server to the Client. Going from the Client to the Server is a bit more problematic due to the way all messages are treated as commands. May work through that while working on the overll problem of User  / NPC interaction.

The core problem is linking this NPC to the User that issues the ASK command.

Proposed Sequence
1. User uses ASK <name> command to trigger a AskMessage to be sent to their Client.
2. The NPC and User ManagedReferences are added to a Contacts Hash list <QuestNPC, MudUser>
3. A new Message class NpcMessage is use to send messages from the Client. When this type of message is recieved by the Server, it checks the Contacts list and routes it to the NPC associated with the User.
4. The NPC responds to the message as needed.
4a. The NPC maintains a state machine kind of logic to manage the dialog with the User.
4b. The NPC maintains a Hash list <MudUser, State> to be able to talk to multiple Users.
NOTE: This could be used to only talk to one User at a time also.
5. repeat 3 and 4 as needed and remove entry from Contacts list when done.
5a. Also remove and clean up state if User leaves the area. Need to detect this.

First thing to do is find out where ALL messages get received by the Server and use the new Message Factory protocol there.
Going back to the original investigation of DarkMud, the UnderstandingDarkMud01.html file shows that PDS calls the Server side object with the ClientSessionListener interface uses receiveMessage() to receive messages from the Client. This object is the MudUser class.
The plan will be to send all command messages as TextMessage objects. All of these will have their message element passed on to the parse() method to be processed as before. New message types will be added after these changes are working.

MudUser.java

Changes to receiveMessage() based on changes made to MudClient for message receiving.
Replaced code with
  try {
      m.rewind();
      handleMessage(MessageFactory.getMessage(m));
  } catch (IOException e) {
      // This only happens if the message type is unknown.
  }
Added handleMessage(). (see code)
Now to change the Client. Again, from prior work, send() is used to output messages to the Server. The send() method is part of a SimpleClient object generated by doConnect() at logon. Both handleMessage() and userInput() call it by using simpleClient.send(). Need to change both of these to use TextMessage objects.
Changes to userInput() and handleMessage().(see code)
Add sendMsgToServer() which is a slightly modified copy of MudUser.sendMsgToClient().(see code)
Ok..all good. Now support for the User's response to the Quest Pop Up can be handled with relative ease.

08jan10
PS #1 is in place now. The next thing is a simple database of Quests.
Quests usually have the following
    A unique ID for ease of management
    A name
    A description
    Flags and counters if the quest can be done multiple times
    A list of things to do or aquire (need a way to record the action, check item list)
    A reward of experience points, item, cash (need a data struct to hold these)
    A link to the next quest

The Plan
The Server will maintain a Hash list of Quests by ID and ManagedReferences.
The Server will have a Hash list for each MudUser object to manage the state of the quests that the Player has active and a list for completed quests.
The Quest active list will have the ID, kill count, and progress state. Everything else comes from the Quest object.  

Quest.class

The class must be Serializable so that it will be compatible with the PDS database system.
Elements
questID Unique number for this quest
name Quest name displayed in the GUI Assignments list area
description Description of the quest used when it is given or when selected from the GUI list
kills Hash list of type and number of kills needed
collection Hash list of type and number of items to collect
exp Experience points awarded on completion
coin Cash awarded on completion
reward Item rewarded (could be a selection list)

QusetNPC will have a list that is build when they are insanciated.
Quest objects are copies to the User's Quest list and deleted when done.
09feb10
Ok, try to implement Quest objects and list for MudUser..only kills list will be active for starters.
The kills list has a Mob ID and a number of kills needed..hmm..MudObjects have an id already,
but this is a system generated unique number..need a MOB type ID for quests..
Adding mobID to MudCharacter..Each sub-class will set it base on what they are.
Zombies use 1000 to 1999, so a series 1000 is any zombie and 1001 is Fred. 1002 is Bill, etc.

MudCharacter.java

Add variable
    private Integer mobID;
Add methods (see code)
    void setMobID(Integer i)
    int getMobID()
    boolean isType( Integer MobType, Integer MobID)
Add constants
    public static final int ZOMBIE = 1000;
    public static final int MUTANT = 2000;
    public static final int UNDEAD = 3000;

Zombie.java

Add to constructor
    setMobID(MudCharacter.ZOMBIE);
NOTE: If a specific Zombie is needed (i.e. Fred), will have to add id to properties file and support.
 

MudUser.java and MudClient.java

Using QuestMesssage to trigger assignments list modification and InfoUpdateMessage
(see code)
Sorta works..removes other assignment..hmm..

Adding questCheck(MudCharacter.ZOMBIE) to MudUser to call from Zombie.java
Always return true for testing.
If true, remove quest #2. Then you can add it again...in theory..it works.
Update repository and update server this week. Add ASK to help list.
Then on to better combat and inventory stuff.