⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 request.py

📁 大型多人在线游戏开发,该书光盘上附带的源码
💻 PY
字号:
# request.py
#
# Implements a high level request dispatcher that 
# validates user input and maps recognized command 
# strings to functions that invoke game behavior.
#
# Author: Matthew Walker
#         mwalker@softhome.net
#


import objmgr
import gameobs
import string
import re
import os
import deferred
import gameserver


# special object id for request handler
ID_REQUEST = -200


class Request:
  """
  Responsible for handling requests from clients and
  invoking the appropriate action in response. Treat
  this as a singleton: create only one.
  """
  sepRE = re.compile(r"\s+")
  global commands
  commands = {}
  global argusage
  argusage = {}

  def __init__(self):
    global __singleton__
    __singleton__ = self
    self.id = ID_REQUEST  # enables addressing by deferred calls
    objmgr.AddObject(self, self.id)

  def Handle(self, clientid, request):
    """
    Decipher a request into a command and arguments.

    clientid - id of the client making the request
    request - request string to be parsed
    """
    # remove leading and trailing whitespace
    request = string.strip(request) 

    # first token is command; remainder is argument string
    try:
      actionlist = self.sepRE.split(request, 1)
    except ValueError:
      print 'Invalid request: %s' % (request,)
      return

    # parse argstring into arg list
    try:
      action, argstr = actionlist
    except ValueError:
      action = actionlist[0]
      argstr = ''

    args = self.sepRE.split(argstr)

    # convert to tuple
    if args == ['']:
      args = () # no args
    else:
      args = tuple(args)  

    retval = _ExecuteCommand(action, clientid, args)
  
    # notify client of response via deferred call to server
    deferred.Call(gameserver.ID_SERVER, 'respond', (retval,))


def _ExecuteCommand(action, clientid, args):
  """ Dispatch command to appropriate action method. """
  action = string.upper(action)
  try:
    retval = apply(commands[action], (clientid,) + args)
  except KeyError:
    import traceback
    traceback.print_exc()
    retval = Response(clientid, 'Invalid command: ' + repr(action) + os.linesep + \
                      'Type \'help\' for more information.')
  except TypeError:
    import traceback
    traceback.print_exc()
    retval = Response(clientid, 'Usage: %s %s' % (action, argusage[action]))

  return retval



#
# Global command functions, entered into a dictionary
# for easy dispatching without the use of a large
# if .. elif .. else block. The commands dictionary
# maps the command keyword to the function reference,
# and the argusage dictionary maps the command keyword
# to a string that describes the required argument for
# the command (if any).
# 
# The docstrings (first comment after function declaration)
# are written for display purposes - type 'help' in a 
# client to see them in action.
#

def ListCommands(clientid):
  """ Show the list of available commands.  """
  commandstr = ''
  commandNames = commands.keys()
  commandNames.sort() # alpha sort
  for command in commandNames:
    if command[0] == '_':  # private command; not for players
      continue
    func = commands[command]
    args = argusage[command]
    commandstr += '%#-20s- %s%s' % (command + ' ' + args, func.__doc__, os.linesep)

  return Response(clientid, 'Command List: ' + os.linesep + commandstr)
commands['HELP'] = ListCommands
argusage['HELP'] = ''
    

def Logout(clientid):
  """ Remove the Player from the game.  """
  player = objmgr.GetPlayerByClientId(clientid)
  objmgr.UnregisterPlayer(clientid, player.id)
  objmgr.RemoveObject(player)

  deferred.Call(gameserver.ID_SERVER, 'pre_close_client', (clientid,))

  return Response(clientid, 'Goodbye, %s. Hope you had fun!' % (player.name,))
commands['LOGOUT'] = Logout
argusage['LOGOUT'] = ''


def EnterRoom(clientid, roomname):
  """ Enter the room identified by name. """
  try:
    room = objmgr.GetRoomByName(roomname)
  except KeyError:
    return Response(clientid, 'Invalid room name: %s' % (roomname,))

  player = objmgr.GetPlayerByClientId(clientid)
  room.EnterRoom(player)

  return Response(clientid, 'You are now in %s' % (room.name,))
commands['ENTER'] = EnterRoom
argusage['ENTER'] = '<roomname>'


def ExitRoom(clientid):
  """ Leave the current room. """
  player = objmgr.GetPlayerByClientId(clientid)
  room = objmgr.GetObject(player.currentRoom)
  if room:
    room.ExitRoom(player)
    return Response(clientid, 'You have left %s' % (room.name,))
  else:
    return Response(clientid, 'You are not in a room.')
commands['EXIT'] = ExitRoom
argusage['EXIT'] = ''


def ListRooms(clientid):
  """ Return a list of available rooms.  """
  roomids = objmgr.GetRoomIds()
  roomstr = ''
  for roomid in roomids:
    room = objmgr.GetObject(roomid)
    roomstr += '%-10s- %s%s' % (room.name, room.sandbox.__doc__, os.linesep)

  return Response(clientid, 'Avaliable Rooms:' + os.linesep + roomstr)
commands['ROOMS'] = ListRooms
argusage['ROOMS'] = ''


def Wave(clientid, targetname):
  """ Wave at a player."""
  target = objmgr.GetPlayerByName(targetname)
  if target is None:
    return Response(clientid, '%s is not in the game.%s' % (targetname, os.linesep))
    
  player = objmgr.GetPlayerByClientId(clientid)
  player._Wave(target.id)

  return Response(clientid, 'You waved at %s.%s' % (targetname, os.linesep))
commands['WAVE'] = Wave
argusage['WAVE'] = '<targetname>'


def Attack(clientid, targetname):
  """ Attack a player."""
  target = objmgr.GetPlayerByName(targetname)
  if target is None:
    return Response(clientid, '%s is not in the game.%s' % (targetname, os.linesep))
    
  player = objmgr.GetPlayerByClientId(clientid)
  player._Attack(target.id)

  return Response(clientid, 'You attacked %s.%s' % (targetname, os.linesep))
commands['ATTACK'] = Attack
argusage['ATTACK'] = '<targetname>'


def Take(clientid, itemname):
  """ Take an item identified by its name. """
  item = objmgr.GetObjectByName(itemname)
  if item is None:
    return Response(clientid, '%s is not in the game.%s' % (itemname, os.linesep))
    
  player = objmgr.GetPlayerByClientId(clientid)
  if not player._AcquireItem(item):
    return Response(clientid, '%s is not in this room.%s' % (itemname, os.linesep))

  return Response(clientid, 'You took %s.%s' % (itemname, os.linesep))
commands['TAKE'] = Take
argusage['TAKE'] = '<itemname>'


def Put(clientid, itemname):
  """ Put an item identified by its name. """
  item = objmgr.GetObjectByName(itemname)
  if item is None:
    return Response(clientid, '%s is not in the game.%s' % (itemname, os.linesep))
    
  player = objmgr.GetPlayerByClientId(clientid)
  if not player._ReleaseItem(item):
    return Response(clientid, 'You do not have %s.%s' % (itemname, os.linesep))

  return Response(clientid, 'You returned %s.%s' % (itemname, os.linesep))
commands['PUT'] = Put
argusage['PUT'] = '<itemname>'


def Equip(clientid, itemname):
  """ Arm yourself with the weapon identified by its name. """
  item = objmgr.GetObjectByName(itemname)
  if item is None:
    return Response(clientid, '%s is not in the game.%s' % (itemname, os.linesep))
    
  player = objmgr.GetPlayerByClientId(clientid)
  if not isinstance(item, gameobs.Weapon):
    return Response(clientid, '%s is not a weapon.%s' % (itemname, os.linesep))

  if not player._EquipWeapon(item):
    return Response(clientid, '%s is not in your inventory.%s' % (itemname, os.linesep))

  return Response(clientid, 'You equipped a %s.%s' % (itemname, os.linesep))
commands['EQUIP'] = Equip
argusage['EQUIP'] = '<itemname>'


def ShowInventory(clientid):
  """ Display your inventory. """
  player = objmgr.GetPlayerByClientId(clientid)
  itemstr = 'You have:' + os.linesep
  for itemid in player.inventory:
    item = objmgr.GetObject(itemid)
    itemstr += '%s%s' % (item.name, os.linesep)

  return Response(clientid, itemstr)
commands['INV'] = ShowInventory
argusage['INV'] = ''


#
# Private commands
#
def Login(clientid, name):
  """ Create a new Player for the given name.  """
  playerid = objmgr.NextId()
  player = gameobs.Player(name, playerid, clientid)  
  objmgr.AddObject(player, playerid)
  objmgr.RegisterPlayer(clientid, playerid)
  return Response(clientid, 'Welcome to the Game, %s. Type \'help\' for a list of commands.' % (name,))
commands['_LOGIN'] = Login
argusage['_LOGIN'] = '<playername>'


#
# Utility functions
#

def ClientMessage(playerid, msg):
  """
  Sends a message to the player associates with the 
  clientid using a deferred call.
  """
  player = objmgr.GetObject(playerid)
  response = Response(player.clientid, msg)
  deferred.Call(gameserver.ID_SERVER, 'respond', (response,))


#
# Utility class
#
class Response:
  """
  Simple structure for returing information to 
  a client.
  """
  def __init__(self, clientid, msg):
    self.clientid = clientid
    self.msg = msg

  def __str__(self):
    return os.linesep + self.msg + os.linesep


def __ModuleInit__():
  """
  Create a single instance of the handler, automatically.
  """
  Request()   # assigns self to __singleton__

__ModuleInit__()  # called at import time


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -