Advertisement
Guest User

Untitled

a guest
Oct 14th, 2016
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.80 KB | None | 0 0
  1. import logging
  2. from eventemitter import EventEmitter
  3.  
  4. from google.protobuf.internal.containers import RepeatedScalarFieldContainer
  5.  
  6. from dota2.enums import EGCBaseClientMsg, ESOMsg, ESOType
  7. from dota2.protobufs import base_gcmessages_pb2 as _gc_base
  8. from dota2.protobufs import dota_gcmessages_client_pb2 as _gc_client
  9. from dota2.protobufs import dota_gcmessages_common_pb2 as _gc_common
  10. from dota2.protobufs import dota_gcmessages_common_match_management_pb2 as \
  11. _gc_common_match_management
  12.  
  13.  
  14. class ProtoNotFound(BaseException):
  15. """Trigger this when cache proto does not exist.
  16. """
  17. pass
  18.  
  19.  
  20. def find_so_proto(type_id):
  21. """Resolves proto message for given type_id
  22.  
  23. :param type_id: SO type
  24. :type type_id: :class:`dota2.enums.ESOType`
  25. :returns: proto message or `None`
  26. """
  27. if not isinstance(type_id, ESOType):
  28. return None
  29.  
  30. proto = getattr(_gc_base, type_id.name, None)
  31. if proto is None:
  32. proto = getattr(_gc_client, type_id.name, None)
  33. if proto is None:
  34. proto = getattr(_gc_common, type_id.name, None)
  35. if proto is None:
  36. proto = getattr(_gc_common_match_management, type_id.name, None)
  37.  
  38. if not proto:
  39. raise ProtoNotFound("Unable to locate proto for: %s" % repr(type_id))
  40. return proto
  41.  
  42.  
  43. class SOBase(object):
  44. def __init__(self):
  45. super(SOBase, self).__init__()
  46.  
  47. #: Shared Object Caches
  48. self.socache = SOCache(self)
  49.  
  50.  
  51. class SOCache(EventEmitter, dict):
  52. version = None #: cache version
  53. owner_soid = None #: type and steamid, no clue what type represents
  54.  
  55. def __init__(self, dota_client):
  56. self._dota = dota_client
  57. self._LOG = logging.getLogger("SOCache")
  58.  
  59. # register our handlers
  60. dota_client.on(ESOMsg.CacheSubscribed,
  61. self._handle_cache_subscribed)
  62. dota_client.on(ESOMsg.UpdateMultiple,
  63. self._handle_update_multiple)
  64. dota_client.on(ESOMsg.CacheUnsubscribed,
  65. self._handle_cache_unsubscribed)
  66. dota_client.on(ESOMsg.Destroy,
  67. self._handle_cache_destroy)
  68. dota_client.on(ESOMsg.Create,
  69. self._handle_cache_create)
  70. dota_client.on(EGCBaseClientMsg.EMsgGCClientWelcome,
  71. self._handle_client_welcome)
  72.  
  73. def __hash__(self):
  74. # pretend that we are a hashable dict, lol
  75. # don't attach more than one SOCache per DotaClient
  76. return hash((self._dota, 42))
  77.  
  78. def emit(self, event, *args):
  79. if event is not None:
  80. self._LOG.debug("Emit event: %s" % repr(event))
  81. super(SOCache, self).emit(event, *args)
  82.  
  83. def __get_validated_proto(self, type_id):
  84. try:
  85. return find_so_proto(type_id)
  86. except ProtoNotFound as e:
  87. self._LOG.error(e.message)
  88. raise
  89.  
  90. def __get_validated_type_id(self, type_id):
  91. try:
  92. return ESOType(type_id)
  93. except ValueError:
  94. self._LOG.error("Unsupported type: %d" % type_id)
  95. raise
  96.  
  97. def _sync_type_id(self, proto, type_id, cache):
  98. self[type_id] = proto.FromString(cache.object_data)\
  99. if not isinstance(cache.object_data, RepeatedScalarFieldContainer)\
  100. else proto.FromString(cache.object_data[0])
  101.  
  102. def _update_cache(self, cache):
  103. try:
  104. type_id = self.__get_validated_type_id(cache.type_id)
  105. proto = self.__get_validated_proto(type_id)
  106. self._sync_type_id(proto, type_id, cache)
  107. except (ProtoNotFound, ValueError):
  108. return False
  109.  
  110. if type_id == ESOType.CSODOTALobby:
  111. self._dota.lobby = self[type_id]
  112. if self._dota.verbose_debug:
  113. self._LOG.debug(
  114. "Received lobby snapshot for lobby ID %s." %
  115. self._dota.lobby.lobby_id)
  116. self._dota.emit('practive_lobby_update', self._dota.party)
  117. elif type_id == ESOType.CSODOTALobbyInvite:
  118. self._dota.lobby_invite = self[type_id]
  119. if self._dota.verbose_debug:
  120. self._LOG.debug(
  121. "Received lobby invite snapshot for group ID %s." %
  122. self._dota.lobby.party_id)
  123. self._dota.emit('lobby_invite_update', self._dota.party)
  124. elif type_id == ESOType.CSODOTAParty:
  125. self._dota.party = self[type_id]
  126. if self._dota.verbose_debug:
  127. self._LOG.debug(
  128. "Received party snapshot for party ID %s." %
  129. self._dota.party.party_id)
  130. self._dota.emit('party_update', self._dota.party)
  131. elif type_id == ESOType.CSODOTAPartyInvite:
  132. self._dota.party_invite = self[type_id]
  133. if self._dota.verbose_debug:
  134. self._LOG.debug(
  135. "Received party invite snapshot for group ID %s." %
  136. self._dota.party_invite.group_id)
  137. self._dota.emit('party_update_invite', self._dota.party_invite)
  138. else:
  139. if self._dota.verbose_debug:
  140. self._LOG.debug("Unknown cache ID at update: %s" %
  141. repr(type_id))
  142.  
  143. self.emit("cache_updated", type_id)
  144.  
  145. def _destroy_cache(self, cache):
  146. try:
  147. type_id = self.__get_validated_type_id(cache.type_id)
  148. proto = self.__get_validated_proto(type_id)
  149. self._sync_type_id(proto, type_id, cache)
  150. except (ProtoNotFound, ValueError):
  151. return False
  152.  
  153. if type_id == ESOType.CSODOTAPartyInvite:
  154. self._dota.party_invite = None
  155. self._dota.emit('party_invite_cleared')
  156. elif type_id == ESOType.CSODOTALobbyInvite:
  157. self._dota.lobby_invite = None
  158. self._dota.emit('lobby_invite_cleared')
  159. else:
  160. if self._dota.verbose_debug:
  161. self._LOG.debug("Unknown cache ID at destroy: %s" %
  162. repr(type_id))
  163.  
  164. self.emit("cache_destroyed", type_id)
  165.  
  166. def _unsubscribe_cache(self, cache):
  167. try:
  168. type_id = self.__get_validated_type_id(cache.type_id)
  169. proto = self.__get_validated_proto(type_id)
  170. self._sync_type_id(proto, type_id, cache)
  171. except (ProtoNotFound, ValueError):
  172. return False
  173.  
  174. if self._dota.lobby and self._dota.lobby.id == cache.owner_soid.id:
  175. self._dota.lobby = None
  176. self._dota.emit('practice_lobby_cleared')
  177. elif self._dota.lobby_invite and self._dota.lobby_invite.group_id == cache.owner_soid.id:
  178. self._dota.lobby_invite = None
  179. self._dota.emit('lobby_invite_cleared')
  180. elif self._dota.party and self._dota.party.id == cache.owner_soid.id:
  181. self._dota.party = None
  182. self._dota.emit('party_cleared')
  183. elif self._dota.party_invite and self._dota.party_invite.group_id == cache.owner_soid.id:
  184. self._dota.party_invite = None
  185. self._dota.emit('party_invite_cleared')
  186. else:
  187. if self._dota.verbose_debug:
  188. self._LOG.debug("Unknown cache ID at unsubscribe: %s" %
  189. repr(type_id))
  190.  
  191. self.emit("cache_unsubscribed", type_id)
  192.  
  193. def _handle_client_welcome(self, message):
  194. for one in message.outofdate_subscribed_caches:
  195. self._handle_cache_subscribed(one)
  196.  
  197. def _handle_cache_subscribed(self, message):
  198. for cache in message.objects:
  199. self._update_cache(cache)
  200.  
  201. def _handle_update_multiple(self, message):
  202. for cache in message.objects_modified:
  203. self._update_cache(cache)
  204.  
  205. def _handle_cache_unsubscribed(self, message):
  206. self._unsubscribe_cache(message)
  207.  
  208. def _handle_cache_destroy(self, message):
  209. self._destroy_cache(message)
  210.  
  211. def _handle_cache_create(self, message):
  212. self._update_cache(message)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement