NetMessenger.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. from direct.directnotify import DirectNotifyGlobal
  2. from direct.distributed.PyDatagram import PyDatagram
  3. from direct.showbase.Messenger import Messenger
  4. import sys
  5. if sys.version_info >= (3, 0):
  6. from pickle import dumps, loads
  7. else:
  8. from cPickle import dumps, loads
  9. # Messages do not need to be in the MESSAGE_TYPES list.
  10. # This is just an optimization. If the message is found
  11. # in this list, it is reduced to an integer index and
  12. # the message string is not sent. Otherwise, the message
  13. # string is sent in the datagram.
  14. MESSAGE_TYPES=(
  15. "avatarOnline",
  16. "avatarOffline",
  17. "create",
  18. "needUberdogCreates",
  19. "transferDo",
  20. )
  21. # This is the reverse look up for the recipient of the
  22. # datagram:
  23. MESSAGE_STRINGS={}
  24. for i in zip(MESSAGE_TYPES, range(1, len(MESSAGE_TYPES)+1)):
  25. MESSAGE_STRINGS[i[0]]=i[1]
  26. class NetMessenger(Messenger):
  27. """
  28. This works very much like the Messenger class except that messages
  29. are sent over the network and (possibly) handled (accepted) on a
  30. remote machine (server).
  31. """
  32. notify = DirectNotifyGlobal.directNotify.newCategory('NetMessenger')
  33. def __init__(self, air, channels):
  34. """
  35. air is the AI Repository.
  36. channels is a list of channel IDs (uint32 values)
  37. """
  38. assert self.notify.debugCall()
  39. Messenger.__init__(self)
  40. self.air=air
  41. self.channels=channels
  42. for i in self.channels:
  43. self.air.registerForChannel(i)
  44. def clear(self):
  45. assert self.notify.debugCall()
  46. for i in self.channels:
  47. self.air.unRegisterChannel(i)
  48. del self.air
  49. del self.channels
  50. Messenger.clear(self)
  51. def send(self, message, sentArgs=[]):
  52. """
  53. Send message to All AI and Uber Dog servers.
  54. """
  55. assert self.notify.debugCall()
  56. datagram = PyDatagram()
  57. # To:
  58. datagram.addUint8(1)
  59. datagram.addChannel(self.channels[0])
  60. # From:
  61. datagram.addChannel(self.air.ourChannel)
  62. #if 1: # We send this just because the air expects it:
  63. # # Add an 'A' for AI
  64. # datagram.addUint8(ord('A'))
  65. messageType=MESSAGE_STRINGS.get(message, 0)
  66. datagram.addUint16(messageType)
  67. if messageType:
  68. datagram.addString(str(dumps(sentArgs)))
  69. else:
  70. datagram.addString(str(dumps((message, sentArgs))))
  71. self.air.send(datagram)
  72. def handle(self, pickleData):
  73. """
  74. Send pickleData from the net on the local netMessenger.
  75. The internal data in pickleData should have a tuple of
  76. (messageString, sendArgsList).
  77. """
  78. assert self.notify.debugCall()
  79. messageType=self.air.getMsgType()
  80. if messageType:
  81. message=MESSAGE_TYPES[messageType-1]
  82. sentArgs=loads(pickleData)
  83. else:
  84. (message, sentArgs) = loads(pickleData)
  85. Messenger.send(self, message, sentArgs=sentArgs)