request.py
上传用户:ghyvgy
上传日期:2009-05-26
资源大小:547k
文件大小:9k
源码类别:

其他游戏

开发平台:

Python

  1. # request.py
  2. #
  3. # Implements a high level request dispatcher that 
  4. # validates user input and maps recognized command 
  5. # strings to functions that invoke game behavior.
  6. #
  7. # Author: Matthew Walker
  8. #         mwalker@softhome.net
  9. #
  10. import objmgr
  11. import gameobs
  12. import string
  13. import re
  14. import os
  15. import deferred
  16. import gameserver
  17. # special object id for request handler
  18. ID_REQUEST = -200
  19. class Request:
  20.   """
  21.   Responsible for handling requests from clients and
  22.   invoking the appropriate action in response. Treat
  23.   this as a singleton: create only one.
  24.   """
  25.   sepRE = re.compile(r"s+")
  26.   global commands
  27.   commands = {}
  28.   global argusage
  29.   argusage = {}
  30.   def __init__(self):
  31.     global __singleton__
  32.     __singleton__ = self
  33.     self.id = ID_REQUEST  # enables addressing by deferred calls
  34.     objmgr.AddObject(self, self.id)
  35.   def Handle(self, clientid, request):
  36.     """
  37.     Decipher a request into a command and arguments.
  38.     clientid - id of the client making the request
  39.     request - request string to be parsed
  40.     """
  41.     # remove leading and trailing whitespace
  42.     request = string.strip(request) 
  43.     # first token is command; remainder is argument string
  44.     try:
  45.       actionlist = self.sepRE.split(request, 1)
  46.     except ValueError:
  47.       print 'Invalid request: %s' % (request,)
  48.       return
  49.     # parse argstring into arg list
  50.     try:
  51.       action, argstr = actionlist
  52.     except ValueError:
  53.       action = actionlist[0]
  54.       argstr = ''
  55.     args = self.sepRE.split(argstr)
  56.     # convert to tuple
  57.     if args == ['']:
  58.       args = () # no args
  59.     else:
  60.       args = tuple(args)  
  61.     retval = _ExecuteCommand(action, clientid, args)
  62.   
  63.     # notify client of response via deferred call to server
  64.     deferred.Call(gameserver.ID_SERVER, 'respond', (retval,))
  65. def _ExecuteCommand(action, clientid, args):
  66.   """ Dispatch command to appropriate action method. """
  67.   action = string.upper(action)
  68.   try:
  69.     retval = apply(commands[action], (clientid,) + args)
  70.   except KeyError:
  71.     import traceback
  72.     traceback.print_exc()
  73.     retval = Response(clientid, 'Invalid command: ' + repr(action) + os.linesep + 
  74.                       'Type 'help' for more information.')
  75.   except TypeError:
  76.     import traceback
  77.     traceback.print_exc()
  78.     retval = Response(clientid, 'Usage: %s %s' % (action, argusage[action]))
  79.   return retval
  80. #
  81. # Global command functions, entered into a dictionary
  82. # for easy dispatching without the use of a large
  83. # if .. elif .. else block. The commands dictionary
  84. # maps the command keyword to the function reference,
  85. # and the argusage dictionary maps the command keyword
  86. # to a string that describes the required argument for
  87. # the command (if any).
  88. # The docstrings (first comment after function declaration)
  89. # are written for display purposes - type 'help' in a 
  90. # client to see them in action.
  91. #
  92. def ListCommands(clientid):
  93.   """ Show the list of available commands.  """
  94.   commandstr = ''
  95.   commandNames = commands.keys()
  96.   commandNames.sort() # alpha sort
  97.   for command in commandNames:
  98.     if command[0] == '_':  # private command; not for players
  99.       continue
  100.     func = commands[command]
  101.     args = argusage[command]
  102.     commandstr += '%#-20s- %s%s' % (command + ' ' + args, func.__doc__, os.linesep)
  103.   return Response(clientid, 'Command List: ' + os.linesep + commandstr)
  104. commands['HELP'] = ListCommands
  105. argusage['HELP'] = ''
  106.     
  107. def Logout(clientid):
  108.   """ Remove the Player from the game.  """
  109.   player = objmgr.GetPlayerByClientId(clientid)
  110.   objmgr.UnregisterPlayer(clientid, player.id)
  111.   objmgr.RemoveObject(player)
  112.   deferred.Call(gameserver.ID_SERVER, 'pre_close_client', (clientid,))
  113.   return Response(clientid, 'Goodbye, %s. Hope you had fun!' % (player.name,))
  114. commands['LOGOUT'] = Logout
  115. argusage['LOGOUT'] = ''
  116. def EnterRoom(clientid, roomname):
  117.   """ Enter the room identified by name. """
  118.   try:
  119.     room = objmgr.GetRoomByName(roomname)
  120.   except KeyError:
  121.     return Response(clientid, 'Invalid room name: %s' % (roomname,))
  122.   player = objmgr.GetPlayerByClientId(clientid)
  123.   room.EnterRoom(player)
  124.   return Response(clientid, 'You are now in %s' % (room.name,))
  125. commands['ENTER'] = EnterRoom
  126. argusage['ENTER'] = '<roomname>'
  127. def ExitRoom(clientid):
  128.   """ Leave the current room. """
  129.   player = objmgr.GetPlayerByClientId(clientid)
  130.   room = objmgr.GetObject(player.currentRoom)
  131.   if room:
  132.     room.ExitRoom(player)
  133.     return Response(clientid, 'You have left %s' % (room.name,))
  134.   else:
  135.     return Response(clientid, 'You are not in a room.')
  136. commands['EXIT'] = ExitRoom
  137. argusage['EXIT'] = ''
  138. def ListRooms(clientid):
  139.   """ Return a list of available rooms.  """
  140.   roomids = objmgr.GetRoomIds()
  141.   roomstr = ''
  142.   for roomid in roomids:
  143.     room = objmgr.GetObject(roomid)
  144.     roomstr += '%-10s- %s%s' % (room.name, room.sandbox.__doc__, os.linesep)
  145.   return Response(clientid, 'Avaliable Rooms:' + os.linesep + roomstr)
  146. commands['ROOMS'] = ListRooms
  147. argusage['ROOMS'] = ''
  148. def Wave(clientid, targetname):
  149.   """ Wave at a player."""
  150.   target = objmgr.GetPlayerByName(targetname)
  151.   if target is None:
  152.     return Response(clientid, '%s is not in the game.%s' % (targetname, os.linesep))
  153.     
  154.   player = objmgr.GetPlayerByClientId(clientid)
  155.   player._Wave(target.id)
  156.   return Response(clientid, 'You waved at %s.%s' % (targetname, os.linesep))
  157. commands['WAVE'] = Wave
  158. argusage['WAVE'] = '<targetname>'
  159. def Attack(clientid, targetname):
  160.   """ Attack a player."""
  161.   target = objmgr.GetPlayerByName(targetname)
  162.   if target is None:
  163.     return Response(clientid, '%s is not in the game.%s' % (targetname, os.linesep))
  164.     
  165.   player = objmgr.GetPlayerByClientId(clientid)
  166.   player._Attack(target.id)
  167.   return Response(clientid, 'You attacked %s.%s' % (targetname, os.linesep))
  168. commands['ATTACK'] = Attack
  169. argusage['ATTACK'] = '<targetname>'
  170. def Take(clientid, itemname):
  171.   """ Take an item identified by its name. """
  172.   item = objmgr.GetObjectByName(itemname)
  173.   if item is None:
  174.     return Response(clientid, '%s is not in the game.%s' % (itemname, os.linesep))
  175.     
  176.   player = objmgr.GetPlayerByClientId(clientid)
  177.   if not player._AcquireItem(item):
  178.     return Response(clientid, '%s is not in this room.%s' % (itemname, os.linesep))
  179.   return Response(clientid, 'You took %s.%s' % (itemname, os.linesep))
  180. commands['TAKE'] = Take
  181. argusage['TAKE'] = '<itemname>'
  182. def Put(clientid, itemname):
  183.   """ Put an item identified by its name. """
  184.   item = objmgr.GetObjectByName(itemname)
  185.   if item is None:
  186.     return Response(clientid, '%s is not in the game.%s' % (itemname, os.linesep))
  187.     
  188.   player = objmgr.GetPlayerByClientId(clientid)
  189.   if not player._ReleaseItem(item):
  190.     return Response(clientid, 'You do not have %s.%s' % (itemname, os.linesep))
  191.   return Response(clientid, 'You returned %s.%s' % (itemname, os.linesep))
  192. commands['PUT'] = Put
  193. argusage['PUT'] = '<itemname>'
  194. def Equip(clientid, itemname):
  195.   """ Arm yourself with the weapon identified by its name. """
  196.   item = objmgr.GetObjectByName(itemname)
  197.   if item is None:
  198.     return Response(clientid, '%s is not in the game.%s' % (itemname, os.linesep))
  199.     
  200.   player = objmgr.GetPlayerByClientId(clientid)
  201.   if not isinstance(item, gameobs.Weapon):
  202.     return Response(clientid, '%s is not a weapon.%s' % (itemname, os.linesep))
  203.   if not player._EquipWeapon(item):
  204.     return Response(clientid, '%s is not in your inventory.%s' % (itemname, os.linesep))
  205.   return Response(clientid, 'You equipped a %s.%s' % (itemname, os.linesep))
  206. commands['EQUIP'] = Equip
  207. argusage['EQUIP'] = '<itemname>'
  208. def ShowInventory(clientid):
  209.   """ Display your inventory. """
  210.   player = objmgr.GetPlayerByClientId(clientid)
  211.   itemstr = 'You have:' + os.linesep
  212.   for itemid in player.inventory:
  213.     item = objmgr.GetObject(itemid)
  214.     itemstr += '%s%s' % (item.name, os.linesep)
  215.   return Response(clientid, itemstr)
  216. commands['INV'] = ShowInventory
  217. argusage['INV'] = ''
  218. #
  219. # Private commands
  220. #
  221. def Login(clientid, name):
  222.   """ Create a new Player for the given name.  """
  223.   playerid = objmgr.NextId()
  224.   player = gameobs.Player(name, playerid, clientid)  
  225.   objmgr.AddObject(player, playerid)
  226.   objmgr.RegisterPlayer(clientid, playerid)
  227.   return Response(clientid, 'Welcome to the Game, %s. Type 'help' for a list of commands.' % (name,))
  228. commands['_LOGIN'] = Login
  229. argusage['_LOGIN'] = '<playername>'
  230. #
  231. # Utility functions
  232. #
  233. def ClientMessage(playerid, msg):
  234.   """
  235.   Sends a message to the player associates with the 
  236.   clientid using a deferred call.
  237.   """
  238.   player = objmgr.GetObject(playerid)
  239.   response = Response(player.clientid, msg)
  240.   deferred.Call(gameserver.ID_SERVER, 'respond', (response,))
  241. #
  242. # Utility class
  243. #
  244. class Response:
  245.   """
  246.   Simple structure for returing information to 
  247.   a client.
  248.   """
  249.   def __init__(self, clientid, msg):
  250.     self.clientid = clientid
  251.     self.msg = msg
  252.   def __str__(self):
  253.     return os.linesep + self.msg + os.linesep
  254. def __ModuleInit__():
  255.   """
  256.   Create a single instance of the handler, automatically.
  257.   """
  258.   Request()   # assigns self to __singleton__
  259. __ModuleInit__()  # called at import time