def _send(self, player_indexes, translated_kwargs): """Send the user message to the given players. :param iterable player_indexes: All players with the same language setting. :param AttrDict translated_kwargs: The translated arguments. """ recipients = RecipientFilter(*player_indexes) recipients.reliable = self.reliable user_message = UserMessage(recipients, self.message_name) if user_message.is_protobuf(): self.protobuf(user_message.buffer, translated_kwargs) user_message.send() else: try: self.bitbuf(user_message.buffer, translated_kwargs) except: # In case of an error during writing to the buffer (e. g. by using # the wrong data type for the write_* methods) reset the buffer # and send the message. This causes the engine to silently ignore # the user message and the server doesn't crash upon creating # another user message. # See also: # https://github.com/Source-Python-Dev-Team/Source.Python/issues/315 user_message.buffer.reset() # Re-raise the exception to make the user aware of the problem raise finally: user_message.send()
def send(self, *args, **kwargs): """Send the message to the given users.""" # Get a recipient filter of the given users recipient = RecipientFilter(*(args or self.users)) # Any parameter to translate? if self._translatable_parameters: # Get a default dictionnary to store the players languages = defaultdict(set) # Get a mapping of the given tokens tokens = ChainMap(kwargs, self.tokens) # Loop through all indexes for index in recipient: if playerinfo_from_index(index).is_fake_client(): continue # Add the current index languages[get_client_language(index)].add(index) # Loop through all languages for language, users in languages.items(): # Get a dictionnary to store the translated strings translated_parameters = dict() # Loop through all translatable parameter for parameter_name in self._translatable_parameters: # Get the current parameter value parameter_value = self[parameter_name] # Is the current parameter not translatable? if not isinstance(parameter_value, TranslationStrings): # No need to go further continue # Translate the current parameter translated_parameters[ parameter_name] = parameter_value.get_string( language, **tokens) # Update the recipient filter recipient.update(*users) # Send the message self._send_message( recipient, **ChainMap(translated_parameters, self)) # Otherwise else: # Send the message self._send_message(recipient, **self)
def send(self, *player_indexes): """Send the user message.""" # We need to handle the ShowMenu user message with bitbuffers # differently, because the maximum size is 255. If the message exceeds # this length, we need to sent it in several parts. if UserMessage.is_protobuf(): recipients = RecipientFilter(*player_indexes) recipients.reliable = self.reliable user_message = UserMessage(recipients, self.message_name) self.protobuf(user_message.buffer, self) user_message.send() else: self.bitbuf(player_indexes, self)
def close(self, *ply_indexes): """Close the menu for the given player indexes. If no indexes were given, the menu will be closed for all players. """ ply_indexes = RecipientFilter(*ply_indexes) for player_index in ply_indexes: queue = self.get_user_queue(player_index) # Try to remove this menu from the queue try: queue.remove(self) except ValueError: # If it fails, do nothing pass else: # If the queue is now empty, send an empty menu to hide # the last menu if not queue: # Send an empty menu self._close(player_index) else: # There is at least one menu in the queue, so refresh to # display it. queue._refresh()
def listener_on_entity_spawned(self, base_entity): if base_entity.classname != 'flashbang_projectile': return index = base_entity.index entity = Entity(index) for player in self._players: if player.inthandle == entity.owner_handle: break else: return temp_entity = TempEntity('BeamFollow') temp_entity.entity_index = index temp_entity.model_index = BEAM_MODEL.index temp_entity.halo_index = BEAM_MODEL.index temp_entity.life_time = 1 temp_entity.start_width = 3 temp_entity.end_width = 3 temp_entity.fade_length = 1 temp_entity.red = 255 temp_entity.green = 255 temp_entity.blue = 255 temp_entity.alpha = 150 temp_entity.create(RecipientFilter())
def listener_on_entity_spawned(self, index, base_entity): if base_entity.classname != 'flashbang_projectile': return entity = Entity(index) if entity.owner_handle not in (self.prisoner.inthandle, self.guard.inthandle): return temp_entity = TempEntity('BeamFollow') temp_entity.entity_index = index temp_entity.model_index = BEAM_MODEL.index temp_entity.halo_index = BEAM_MODEL.index temp_entity.life_time = 1 temp_entity.start_width = 3 temp_entity.end_width = 3 temp_entity.fade_length = 1 temp_entity.red = 255 temp_entity.green = 255 temp_entity.blue = 255 temp_entity.alpha = 150 temp_entity.create(RecipientFilter())
def _send(self, player_indexes, translated_kwargs): """Send the user message to the given players. :param iterable player_indexes: All players with the same language setting. :param AttrDict translated_kwargs: The translated arguments. """ recipients = RecipientFilter(*player_indexes) recipients.reliable = self.reliable user_message = UserMessage(recipients, self.message_name) if user_message.is_protobuf(): self.protobuf(user_message.buffer, translated_kwargs) else: self.bitbuf(user_message.buffer, translated_kwargs) user_message.send()
def _pre_user_message_begin(args): try: # Replace original recipients filter tmp_recipients = make_object(BaseRecipientFilter, args[1]) except RuntimeError: # Patch for issue #314 tmp_recipients = RecipientFilter.from_abstract_pointer(args[1]) _recipients.update(*tuple(tmp_recipients), clear=True) args[1] = _recipients
def send(self, *player_indexes, **tokens): """Send the user message.""" player_indexes = RecipientFilter(*player_indexes) for language, indexes in self._categorize_players_by_language( player_indexes).items(): translated_kwargs = AttrDict(self) translated_kwargs.update( self._get_translated_kwargs(language, tokens)) self._send(indexes, translated_kwargs)
def pre_playback_temp_entity(stack_data): """Handle pre hooks.""" temp_entity = TempEntity(stack_data[3]) try: recipients = make_object(RecipientFilter, stack_data[1]) except RuntimeError: global _recipients _recipients = RecipientFilter.from_abstract_pointer(stack_data[1]) stack_data[1] = recipients = _recipients return temp_entity.template.handle_hook(temp_entity, recipients)
def send(self, *ply_indexes): """Send the menu to the given player indexes. If no indexes were given, the menu will be sent to every player. """ ply_indexes = RecipientFilter(*ply_indexes) for player_index in ply_indexes: queue = self.get_user_queue(player_index) queue.append(self) queue._refresh()
def bitbuf(self, player_indexes, kwargs): """Send the ShowMenu with bitbuf.""" menu_string = kwargs.menu_string length = len(menu_string) recipients = RecipientFilter(*player_indexes) recipients.reliable = self.reliable while True: user_message = UserMessage(recipients, self.message_name) buffer = user_message.buffer buffer.write_word(kwargs.valid_slots) buffer.write_char(kwargs.display_time) buffer.write_byte(length > self.chunk_size) buffer.write_string(menu_string[:self.chunk_size]) user_message.send() if length > self.chunk_size: menu_string = menu_string[self.chunk_size:] length -= self.chunk_size else: break
def __call__(self, recipients=None, *args, **kwargs): """Sends the effect.""" recipients = RecipientFilter() if recipients is None else recipients arguments = self.args.copy() _update_ordered_dict(arguments, args, kwargs) # Update model's path to the model's index model = arguments.get('model') if model and isinstance(model, str): arguments['model'] = _model_indexes[model] # Call the function self.function(recipients, *arguments.values())
def _pre_user_message_begin(args): try: # Replace original recipients filter tmp_recipients = make_object(BaseRecipientFilter, args[1]) _recipients.update(*tuple(tmp_recipients), clear=True) except RuntimeError: # Patch for issue #314 tmp_recipients = RecipientFilter() (args[1] + 4).copy( get_object_pointer(tmp_recipients) + 4, get_size(RecipientFilter) - 4) _recipients.update(*tuple(tmp_recipients), clear=True) args[1] = _recipients
def _pre_send_user_message(args): message_index = args[2] user_message_hooks = HookUserMessage.hooks[message_index] protobuf_user_message_hooks = HookProtobufUserMessage.hooks[ message_index] # No need to do anything behind this if no listener is registered if not user_message_hooks and not protobuf_user_message_hooks: return try: # Replace original recipients filter tmp_recipients = make_object(BaseRecipientFilter, args[1]) except RuntimeError: # Patch for issue #314 tmp_recipients = RecipientFilter.from_abstract_pointer(args[1]) _recipients.update(*tuple(tmp_recipients), clear=True) args[1] = _recipients try: buffer = make_object(ProtobufMessage, args[3]) wrapped_from_abstract = False except RuntimeError: # Patch for issue #390 - UserMessage was created by another plugin. buffer = ProtobufMessage.from_abstract_pointer(args[3]) wrapped_from_abstract = True protobuf_user_message_hooks.notify(_recipients, buffer) # No need to do anything behind this if no listener is registered if user_message_hooks: try: impl = get_user_message_impl(message_index) except NotImplementedError: impl = None if impl is not None: data = impl.read(buffer) user_message_hooks.notify(_recipients, data) # Update buffer if data has been changed if data.has_been_changed(): buffer.clear() impl.write(buffer, data) # If we wrapped the buffer from an abstract pointer, make sure to # apply any changes that may have been made back into the original. if wrapped_from_abstract: buffer.parse_to_abstract_pointer(args[3])
def play(self, *recipients): """Play the sound.""" # Get the recipients to play the sound to recipients = RecipientFilter(*recipients) # Is the sound precached? if not self.is_precached: # Precache the sound self.precache() # Play the sound engine_sound.emit_sound( recipients, self.index, self.channel, self.sample, self.volume, self.attenuation, self.flags, self.pitch, self.origin, self.direction, self.origins, self.update_positions, self.sound_time, self.speaker_entity)
def _pre_send_user_message(args): message_index = args[2] user_message_hooks = HookUserMessage.hooks[message_index] protobuf_user_message_hooks = HookProtobufUserMessage.hooks[ message_index] # No need to do anything behind this if no listener is registered if not user_message_hooks and not protobuf_user_message_hooks: return try: # Replace original recipients filter tmp_recipients = make_object(BaseRecipientFilter, args[1]) _recipients.update(*tuple(tmp_recipients), clear=True) except RuntimeError: # Patch for issue #314 tmp_recipients = RecipientFilter() (args[1] + 4).copy( get_object_pointer(tmp_recipients) + 4, get_size(RecipientFilter) - 4) _recipients.update(*tuple(tmp_recipients), clear=True) args[1] = _recipients buffer = make_object(ProtobufMessage, args[3]) protobuf_user_message_hooks.notify(_recipients, buffer) # No need to do anything behind this if no listener is registered if not user_message_hooks: return try: impl = get_user_message_impl(message_index) except NotImplementedError: return data = impl.read(buffer) user_message_hooks.notify(_recipients, data) # Update buffer if data has been changed if data.has_been_changed(): buffer.clear() impl.write(buffer, data)
def send(self, *player_indexes, **tokens): """Send the Dialog message to the appropriate recipients. :param player_indexes: Values can be a player index, multiple player indexes (star args), a :class:`filters.players.PlayerIter` instance, or a :class:`filters.recipients.RecipientFilter` instance. :param tokens: Keyword arguments used to replace values in messages. """ # Get a recipient filter of the given users recipients = RecipientFilter(*player_indexes) # Get the KeyValues instance keyvalues = KeyValues(self.message_type.name.lower()) # Set the time for the message to display keyvalues.set_int('time', self.time) # Loop through all recipients for index in recipients: # Get a Player instance for the current player player = Player(index) # Is the player not human? if player.is_fake_client(): continue # Get the level for the message level = self._get_player_level(player.userid) # Set the level for the player keyvalues.set_int('level', level) # Set the title (value should be server IP address) keyvalues.set_string( 'title', self._get_text(self.title, player, **tokens)) # Set any remaining keyvalues self._set_keyvalues(keyvalues, player, **tokens) # Send the message create_message(player.edict, self.message_type, keyvalues)
def play(self, *recipients): """Play the sound. :param recipients: Players who will hear the sound. """ # Done here to fix a cyclic import... from filters.recipients import RecipientFilter # Get the recipients to play the sound to recipients = RecipientFilter(*recipients) # Is the sound precached? if not self.is_precached: # Precache the sound self.precache() # Play the sound self._play(recipients)
def create(self, *recipients, delay=0.0, **aliases): """Create the temp entity effect. :param RecipientFilter recipients: The recipient filter listing the players to send the effect to. :param float delay: The delay before creating the effect. :param dict aliases: Any aliases to set before creating the temp entity effect. """ # Get a recipient filter matching the given players... recipients = RecipientFilter(*recipients) # Loop trhough all given aliases... for alias, value in aliases.items(): # Set the alias to the given value... setattr(self, alias, value) # Create the temp entity effect... super().create(recipients, delay)
def tick(self): for index, (attach_to, start_vector) in self.items(): if attach_to == VectorAttachTo.VIEW_COORDINATES: end_vector = players[index].view_coordinates else: end_vector = players[index].origin if end_vector is None: return round_vector(end_vector, EDITOR_STEP_UNITS) box(RecipientFilter(index), start_vector, end_vector, color=EDITOR_LINE_COLOR, life_time=TICK_REPEAT_INTERVAL, halo=EDITOR_LINE_MODEL, model=EDITOR_LINE_MODEL, start_width=EDITOR_LINE_WIDTH, end_width=EDITOR_LINE_WIDTH)
def send(self, userid): msg_index = get_message_index(self.name) if msg_index == -1: import es dbgmsg(0, 'Invalid UserMessage type: {}'.format(self.name)) return try: index = index_from_userid(atoi(userid)) except ValueError: return # We need to save the RecipientFilter instance here. Otherwise it would # get garbage collected before it is send. recipients = RecipientFilter(index) user_message = UserMessage(recipients, self.name) buffer = user_message.buffer for type_name, value in self: self._write(buffer, type_name, value) user_message.send()
def send(self, *ply_indexes, **tokens): """Send the menu to the given player indexes. If no indexes were given, the menu will be sent to every player. :param ply_indexes: Player indexes that should receive the menu. :param tokens: Translation tokens for menu options, title and description. """ ply_indexes = tuple(RecipientFilter(*ply_indexes)) if not ply_indexes: return # Update option tokens for option in self: try: option.text.tokens.update(**tokens) except AttributeError: # Not a _MenuData or TranslationStrings instance pass # Update title if existant try: self.title.tokens.update(**tokens) except AttributeError: pass # Update description if existant try: self.description.tokens.update(**tokens) except AttributeError: pass for player_index in ply_indexes: queue = self.get_user_queue(player_index) queue.append(self) queue._refresh()
def append_zone(self): recipients = RecipientFilter() recipients.remove_all_players() self.append(recipients)
# ============================================================================= # >> ALL DECLARATION # ============================================================================= __all__ = ( 'HookUserMessageBase', 'HookBitBufferUserMessage', 'HookProtobufUserMessage', 'HookUserMessage', ) # ============================================================================= # >> GLOBAL VARIABLES # ============================================================================= _user_message_data = None _recipients = RecipientFilter() # ============================================================================= # >> CLASSES # ============================================================================= class HookUserMessageBase(AutoUnload): """Base decorator for user message hooks.""" def __init__(self, user_message): """Create a new user message hook. :param int/str user_message: The user message index or name to hook. :raise TypeError: Raised if ``user_message`` is not and int or str. :raise ValueError: