Esempio n. 1
0
async def _destroy_instance(entity: Entity,
                            parent_alias: str,
                            entity_id_to_delete: int,
                            force=False):
    from core.src.world.builder import world_repository
    if not await world_repository.entity_exists(entity_id_to_delete):
        await emit_msg(entity, 'Entity does not exists, use cleanup (bug)')
        return
    entity_to_delete = Entity(entity_id_to_delete)
    await load_components(entity_to_delete,
                          (SystemComponent, 'instance_of', 'character'))
    system_component = entity_to_delete.get_component(SystemComponent)
    if system_component.character:
        await emit_msg(entity, 'Cannot destroy characters with this command')
        return
    if force != '--force':
        if system_component.instance_of and (parent_alias !=
                                             system_component.instance_of):
            await emit_msg(
                entity,
                'Entity {} is not type <{}>, it\'s <{}> instead'.format(
                    entity_id_to_delete, parent_alias,
                    system_component.instance_of))
            return
    res = await world_repository.delete_entity(entity_id_to_delete)
    return res
Esempio n. 2
0
async def emit_room_sys_msg(entity: Entity, event_type: str, details: typing.Dict, room=None, include_origin=True):
    from core.src.world.builder import transport
    assert isinstance(details, dict)
    room = room or (entity.get_room() or await get_current_room(entity))
    listeners = await get_eligible_listeners_for_room(room)
    if listeners:
        listeners = listeners if not include_origin else [e for e in listeners if e.entity_id != entity.entity_id]
        listeners and (
            await batch_load_components((SystemComponent, 'connection'), PositionComponent, entities=listeners)
        )
    futures = []
    for entity in listeners:
        position = entity.get_component(PositionComponent)
        if position.coord == room.position.coord and entity.get_component(SystemComponent).connection:
            payload = {
                "event": event_type,
                "target": "entity",
                "details": details,
                "position": room.position.value
            }
            futures.append(
                transport.send_system_event(
                    entity.get_component(SystemComponent).connection.value,
                    payload
                )
            )
    await asyncio.gather(*futures)
    async def _test_stuff_struct_component(self):
        class TestComponent2(StructComponent):
            enum = ComponentTypeEnum.SYSTEM
            meta = (
                ('weirdstuff', str),
                ('manystuffhere', list),
                ('integerrr', int),
                ('boolean', bool),
                ('a', dict)
            )

        class TestComponent(StructComponent):
            enum = ComponentTypeEnum.INVENTORY
            meta = (
                ('weirdstuff', str),
                ('manystuffhere', list),
                ('integerrr', int),
                ('boolean', bool),
                ('a', dict)
            )
            indexes = ('weirdstuff', )

        ent = Entity(444)
        c3 = TestComponent().weirdstuff.set('weirdstuff').a.set('key', 'value').manystuffhere.append(3)
        c4 = TestComponent2().weirdstuff.set('weirdstuff2').a.set('key', 'value2').manystuffhere.append(6)
        ent.set_for_update(c3).set_for_update(c4)
        await self.sut.update_entities(ent)
        res = await self.sut.read_struct_components_for_entity(444, TestComponent, TestComponent2)
        self.assertEqual(res[c3.enum].weirdstuff, 'weirdstuff')
        self.assertEqual(res[c3.enum].a, {'key': 'value'})
        self.assertEqual(res[c4.enum].weirdstuff, 'weirdstuff2')
        self.assertEqual(res[c4.enum].a, {'key': 'value2'})

        self.test_success = True
Esempio n. 4
0
async def cast_entity(
        entity: Entity,
        position: PositionComponent,
        update=True,
        on_connect=False,
        reason=None
):
    assert isinstance(position, PositionComponent)
    from core.src.world.builder import events_subscriber_service, events_publisher_service
    loop = asyncio.get_event_loop()
    if update:
        current_position = await get_components_for_entity(entity, (PositionComponent, 'coord'))
        position.add_previous_position(current_position)
        entity = entity.set_for_update(position).set_room(Room(position))
        update_response = await update_entities(entity.set_for_update(position))
        if not update_response:
            LOGGER.core.error(
                'Impossible to cast entity {}'.format(entity.entity_id))
            return
    area = Area(position).make_coordinates()
    listeners = await get_eligible_listeners_for_area(area)
    entity.entity_id in listeners and listeners.remove(entity.entity_id)
    if on_connect:
        await events_publisher_service.on_entity_appear_position(entity, position, reason, targets=listeners)
        loop.create_task(events_subscriber_service.subscribe_events(entity))
    else:
        pass
        await events_publisher_service.on_entity_change_position(entity, position, reason, targets=listeners)
    entity.set_component(position)
    return True
Esempio n. 5
0
def move_entity_from_container(
        entity: Entity,
        target: (PositionComponent, InventoryComponent),
        current_owner: Entity = None
):
    current_position = entity.get_component(PositionComponent)
    if current_position.parent_of:
        assert current_owner and current_owner.entity_id == current_position.parent_of, (
                current_owner and current_owner.entity_id, current_position.parent_of
        )
        current_owner.get_component(InventoryComponent).content.remove(entity.entity_id)
        current_owner.set_for_update(current_owner.get_component(InventoryComponent))

    if isinstance(target, InventoryComponent):
        target_owner = target.owned_by()
        new_position = PositionComponent().parent_of.set(target_owner.entity_id).coord.null()
        new_position.add_previous_position(current_position)
        target.content.append(entity.entity_id)
        target_owner.set_for_update(target)
        entity.set_for_update(new_position)

    elif isinstance(target, PositionComponent):
        assert target.coord.value
        new_position = PositionComponent().parent_of.null().coord.set(target.coord.value)
        entity.set_for_update(new_position)

    else:
        raise ValueError('Target must be type PosComponent or ContainerComponent, is: %s' % target)
    return entity
    async def _test_selective_repo_queries(self):

        class TestComponent(StructComponent):
            enum = 1
            key = enum
            meta = (
                ('weirdstuff', str),
                ('manystuffhere', list),
                ('integerrr', int),
                ('boolean', bool),
                ('a', dict)
            )

        c = TestComponent().weirdstuff.set('weirdstuff').a.set('key', 'value').manystuffhere.append(3)
        entity = Entity(123)
        entity.set_for_update(c)
        await self.sut.update_entities(entity)
        res = await self.sut.read_struct_components_for_entities([123], (TestComponent, 'weirdstuff'))
        r = res[123][c.enum]
        self.assertEqual(r.weirdstuff, 'weirdstuff')
        self.assertEqual(r.manystuffhere, [])
        self.assertEqual(r.integerrr, 0)
        self.assertEqual(r.boolean, False)
        self.assertEqual(r.a, {})
        self.test_success = True
Esempio n. 7
0
async def get_current_room(entity: Entity, populate=True):
    from core.src.world.builder import map_repository
    not entity.get_component(PositionComponent) and await load_components(entity, PositionComponent)
    room = await map_repository.get_room(entity.get_component(PositionComponent), populate=populate)
    populate and await room.populate_content()
    entity.set_room(room)
    return room
Esempio n. 8
0
    async def on_message(self, message: typing.Dict):
        assert message['c'] == 'cmd'
        if message['n'] not in self._enabled_channels:
            LOGGER.core.error('Error, message received on closed channel: %s',
                              message)
            return

        try:
            data = message['d'].strip().split(' ')
            if not data:
                raise TypeError('Empty command?')

            entity = Entity(message['e_id'], itsme=True)
            entity.set_component(SystemComponent(connection=message['n']))

            command = self._commands[data[0].lower()]
            if getattr(command, 'get_self', False):
                await self._commands[data[0]](entity, *data)
            else:
                await self._commands[data[0]](entity, *data[1:])
        except KeyError as exc:
            if settings.RUNNING_TESTS:
                raise
            await self._on_error(message, "Command not found: %s" % data[0])
            LOGGER.core.exception('Unhandled exception %s', exc)
        except TypeError as exc:
            if settings.RUNNING_TESTS:
                raise
            await self._on_error(message, "Command error: %s" % str(exc))
            LOGGER.core.exception('Unhandled exception %s', exc)
        except Exception as exc:
            LOGGER.core.exception('Unhandled exception %s', exc)
            print(exc)
Esempio n. 9
0
 async def on_event(self, entity_id: int, message: typing.Dict,
                    room: typing.Tuple, transport_id: str):
     room = PositionComponent(coord='{},{},{}'.format(*room))
     entity = Entity(entity_id).set_component(
         SystemComponent().connection.set(transport_id))
     await load_components(entity, PositionComponent)
     curr_pos = entity.get_component(PositionComponent)
     interest_type = await self._get_message_interest_type(
         entity, room, curr_pos)
     if not interest_type.value:
         return
     await self.publish_event(entity, message, room, interest_type,
                              curr_pos)
Esempio n. 10
0
async def clean_rooms_from_stales_instances(instance_type='character'):
    from core.src.world.components.system import SystemComponent
    from core.src.world.builder import world_repository
    from core.src.world.utils.entity_utils import batch_load_components
    from core.src.world.actions.system.disconnect import disconnect_entity
    from core.src.world.builder import map_repository
    entity_ids_with_connection_component_active = await world_repository.get_entity_ids_with_components_having_value(
        (SystemComponent, 'instance_of', instance_type)
    )
    if not entity_ids_with_connection_component_active:
        return []
    entities = [Entity(eid) for eid in entity_ids_with_connection_component_active]
    await batch_load_components(PositionComponent, SystemComponent, entities=entities)
    entities_without_connection_component_and_position = [
        e for e in entities if not e.get_component(SystemComponent).connection
        and e.get_component(PositionComponent).coord
    ]
    rooms = await map_repository.get_rooms(
        *(e.get_component(PositionComponent) for e in entities_without_connection_component_and_position)
    )
    stales = []
    for i, room in enumerate(rooms):
        if entities_without_connection_component_and_position[i].entity_id in room.entity_ids:
            stales.append(entities_without_connection_component_and_position[i])
    LOGGER.core.error('Error, found stales entities: %s' % str([x.entity_id for x in stales]))
    for entity in stales:
        await disconnect_entity(entity, msg=False)
Esempio n. 11
0
 async def _get_character_movement_message(self, entity, message,
                                           interest_type,
                                           curr_pos) -> typing.Dict:
     assert interest_type
     evaluated_emitter_entity = await load_components(
         Entity(message['en']), AttributesComponent)
     payload = {
         "event": "move",
         "entity": {
             "name":
             evaluated_emitter_entity.get_component(
                 AttributesComponent).name,
             "id":
             message['en']
         },
         'from': message['prev'],
         'to': message['curr']
     }
     if message['curr'] == curr_pos.list_coordinates:
         assert message['prev'] != curr_pos
         assert interest_type == InterestType.LOCAL
         payload['action'] = "join"
         payload['direction'] = self._gather_movement_direction(
             message, "join")
     elif message['prev'] == curr_pos.list_coordinates:
         assert message['curr'] != curr_pos
         assert interest_type != InterestType.LOCAL
         payload['action'] = "leave"
         payload['direction'] = self._gather_movement_direction(
             message, "leave")
     else:
         raise ValueError('This should not be here: %s (%s)' %
                          (message, curr_pos.value))
     return payload
    async def create_character(sid, payload):
        token = auth_service.decode_session_token(payload['token'])
        assert token['context'] == 'world:create'
        system_component = SystemComponent()\
            .instance_of.set('character')\
            .created_at.set(int(time.time()))\
            .receive_events.enable()\
            .user_id.set(token['data']['user_id'])

        attributes = AttributesComponent().name.set(payload['name']).keyword.set('uomo')
        entity = Entity() \
            .set_for_update(system_component) \
            .set_for_update(attributes)

        entity = await world_repository.save_entity(entity)
        """
        URGENT - TODO - FIX - Completely move characters allocation outside of SQL.
        Create a "UserID Component" to pair the character in the ECS with the ecosystem uuid,
        as we do for the connection.
        """
        from core.src.auth.database import init_db, db
        init_db(db)
        character_id = psql_character_repository.store_new_character(
            token['data']['user_id'], payload["name"]
        ).character_id
        try:
            db.close()
        except:
            # FIXME - This shouldn't be here, but we miss the "store_new_character" HTTP endpoint yet.
            pass
        """
        Fix ends here, probably
        """
        redis_characters_index_repository.set_entity_id(character_id, entity.entity_id)
        await sio.emit('create', {'success': True, 'character_id': character_id}, to=sid)
Esempio n. 13
0
async def look_at_target(entity: Entity, *arguments: str):
    if len(arguments) > 1:
        await emit_msg(entity,
                       'Command error - Nested targets not implemented yet')
        return
    target_entity = await search_entity_in_sight_by_keyword(
        entity, arguments[0])
    if not target_entity:
        await emit_msg(entity, messages.missing_target())
    elif entity.entity_id == target_entity.entity_id:
        await emit_msg(entity, messages.self_look())
    elif not await ensure_same_position(entity, target_entity):
        await emit_msg(entity, messages.missing_target())
    else:
        if await check_entity_can_receive_messages(target_entity):
            # Avoid to send messages to... knives, for example :-)
            await emit_msg(
                target_entity,
                messages.entity_looks_at_you(
                    entity.get_component(AttributesComponent).keyword))

        await emit_room_msg(
            origin=entity,
            target=target_entity,
            message_template=messages.entity_looks_at_entity_template())
        await emit_msg(
            entity,
            messages.look_at_entity(
                target_entity.get_component(AttributesComponent).keyword)),
        await emit_sys_msg(entity, "look", target_entity)
Esempio n. 14
0
 async def populate_content(self):
     entities = [Entity(eid) for eid in self.entity_ids]
     if not entities:
         return self
     await batch_load_components(AttributesComponent, entities=entities)
     for entity in entities:
         self.add_entity(entity)
     return self
Esempio n. 15
0
async def follow(entity: Entity, *arguments: str):
    from core.src.world.builder import follow_system_manager
    if not len(arguments):
        return await unfollow(entity)
    assert len(arguments) == 1
    target_entity = await search_entity_in_sight_by_keyword(
        entity, arguments[0])
    if not target_entity:
        await emit_msg(entity, messages.target_not_found())
    elif entity.entity_id == target_entity.entity_id:
        if follow_system_manager.is_following_someone(entity.entity_id):
            await unfollow(entity)
        else:
            await emit_msg(entity, messages.not_following_anyone())
    elif follow_system_manager.is_follow_repetition(entity.entity_id,
                                                    target_entity.entity_id):
        await emit_msg(entity, messages.already_following_that_target())
    elif follow_system_manager.is_follow_loop(entity, target_entity):
        await emit_msg(entity, messages.follow_is_loop())
    elif not await ensure_same_position(entity, target_entity):
        await emit_msg(entity, messages.target_not_found())
    else:
        previous_target = follow_system_manager.get_follow_target(
            entity.entity_id)
        if previous_target:
            await emit_msg(
                previous_target,
                messages.entity_stop_following_you(
                    entity.get_component(AttributesComponent).keyword))
            follow_system_manager.stop_following(entity.entity_id)
        follow_system_manager.follow_entity(entity.entity_id,
                                            target_entity.entity_id)
        await asyncio.gather(
            emit_msg(
                entity,
                messages.follow_entity(
                    target_entity.get_component(AttributesComponent).keyword)),
            emit_msg(
                target_entity,
                messages.entity_is_following_you(
                    entity.get_component(AttributesComponent).keyword)))
        await emit_room_msg(
            origin=entity,
            target=target_entity,
            message_template=messages.entity_follows_entity_template(),
        )
Esempio n. 16
0
async def whoami(entity: Entity):
    await load_components(entity, AttributesComponent)
    await emit_msg(
        entity,
        json.dumps({
            "event": "whoami",
            "id": entity.entity_id,
            "name": entity.get_component(AttributesComponent).name.value
        }))
Esempio n. 17
0
 async def on_message(self, message: typing.Dict):
     entity = Entity(message['e_id'], itsme=True).set_component(
         SystemComponent().connection.set(message['n']))
     if message['c'] == 'connected':
         await self.on_connect(entity)
     elif message['c'] == 'disconnected':
         await self.on_disconnect(entity)
     else:
         raise ValueError('wtf?!')
Esempio n. 18
0
async def get_room_at_direction(entity: Entity, direction_enum, populate=True):
    from core.src.world.builder import map_repository
    delta = direction_to_coords_delta(direction_enum)
    if not delta:
        return
    await load_components(entity, PositionComponent)
    look_cords = apply_delta_to_position(entity.get_component(PositionComponent), delta)
    room = await map_repository.get_room(look_cords, populate=populate)
    populate and await room.populate_content()
    return room
Esempio n. 19
0
async def get_eligible_listeners_for_room(pos: (Room, PositionComponent)) -> typing.List[Entity]:
    """
    Returns the list of entities ids that are ables to receive messages in the selected room.
    The "room" argument is a PosComponent or a Room Object.
    """
    if isinstance(pos, Room):
        pos = pos.position
    from core.src.world.builder import map_repository
    entities_room = [Entity(e) for e in await map_repository.get_room_content(pos)]
    if not entities_room:
        return []
    await batch_load_components((SystemComponent, 'receive_events'), entities=entities_room)
    return [e for e in entities_room if e.get_component(SystemComponent).receive_events]
Esempio n. 20
0
 async def on_disconnect(self, entity: Entity):
     current_connection = (
         await self.world_repository.read_struct_components_for_entity(
             entity.entity_id,
             (SystemComponent, 'connection')))[SystemComponent.enum]
     if current_connection.connection.value != entity.get_component(
             SystemComponent).connection.value:
         return
     await disconnect_entity(entity, msg=False)
     self.events_subscriber_service.remove_observer_for_entity_id(
         entity.entity_id)
     self.manager.remove_transport(entity.entity_id)
     await self.events_subscriber_service.unsubscribe_all(entity)
Esempio n. 21
0
async def drop(entity: Entity, keyword: str):
    await load_components(entity, PositionComponent, InventoryComponent)
    inventory = entity.get_component(InventoryComponent)
    items = await search_entities_in_container_by_keyword(inventory, keyword)
    msgs_stack = get_stacker()
    items_to_drop = []
    for item in items:
        items_to_drop.append(
            move_entity_from_container(
                item,
                target=entity.get_component(PositionComponent),
                current_owner=entity))
    if not items_to_drop:
        await emit_msg(entity, messages.target_not_found())
        return
    entity.set_for_update(inventory)
    msgs_stack.add(
        emit_sys_msg(entity, 'remove_items',
                     messages.items_to_message(items_to_drop)),
        emit_room_sys_msg(entity, 'add_items',
                          messages.items_to_message(items_to_drop)))
    if len(items_to_drop) == 1:
        msgs_stack.add(
            emit_msg(entity, messages.on_drop_item(items[0])),
            emit_room_msg(origin=entity,
                          message_template=messages.on_entity_drop_item(
                              items[0])))
    else:
        msgs_stack.add(
            emit_msg(entity, messages.on_drop_multiple_items()),
            emit_room_msg(
                origin=entity,
                message_template=messages.on_entity_drops_multiple_items()))
    if not await update_entities(entity, *items_to_drop):
        await emit_msg(entity, messages.target_not_found())
        msgs_stack.cancel()
    else:
        await msgs_stack.execute()
Esempio n. 22
0
async def check_entities_connection_status() -> typing.List[typing.Dict]:
    """
    Check the match between the transport repository and the ECS status.
    If Entities with Connection component valued are found, but there is no match in the repository,
    the channel is removed from the ECS and the entity is removed from the room.

    Return details on the still active entities.
    """
    from core.src.world.builder import world_repository
    from core.src.world.components.system import SystemComponent
    from core.src.world.builder import channels_repository
    from core.src.world.builder import map_repository, cmds_observer

    entity_ids_with_connection_component_active = await world_repository.get_entity_ids_with_valued_components(
        (SystemComponent, 'connection')
    )
    if not entity_ids_with_connection_component_active:
        return []
    entities = [Entity(eid) for eid in entity_ids_with_connection_component_active]

    await batch_load_components(PositionComponent, (SystemComponent, 'connection'), entities=entities)
    components_values = []
    entities_by_id = {}
    for entity in entities:
        components_values.append(entity.get_component(SystemComponent).connection.value)
        entities_by_id[entity.entity_id] = entity
    to_update = []
    online = []
    if not components_values:
        return online
    channels = channels_repository.get_many(*components_values)
    for i, ch in enumerate(channels.values()):
        if not ch:
            entity = entities[i]
            to_update.append(entity)
            await map_repository.remove_entity_from_map(
                entity_ids_with_connection_component_active[i],
                entity.get_component(PositionComponent)
            )
        else:
            cmds_observer.enable_channel(ch.id)
            online.append(
                {
                    'entity_id': entity_ids_with_connection_component_active[i],
                    'channel_id': ch.id
                }
            )
    await world_repository.update_entities(*to_update)
    return online
Esempio n. 23
0
 async def on_connect(self, entity: Entity):
     connection_id = entity.get_component(SystemComponent).connection.value
     self.events_subscriber_service.add_observer_for_entity_id(
         entity.entity_id, self.pubsub_observer)
     await update_entities(
         entity.set_for_update(
             SystemComponent().connection.set(connection_id)))
     await load_components(entity, PositionComponent)
     if not entity.get_component(PositionComponent).coord:
         await cast_entity(entity,
                           get_base_room_for_entity(entity),
                           on_connect=True,
                           reason="connect")
         self.loop.create_task(self.greet(entity))
     else:
         await cast_entity(entity,
                           entity.get_component(PositionComponent),
                           update=False,
                           on_connect=True,
                           reason="connect")
     self.manager.set_transport(entity.entity_id, connection_id)
     self.commands_observer.enable_channel(connection_id)
     self.loop.create_task(look(entity))
     self.loop.create_task(getmap(entity))
Esempio n. 24
0
async def emit_room_msg(origin: Entity, message_template, target: Entity = None, room=None):
    """
    Emit a room message in the same room of "origin".
    The room can be overridden with the room= keyword argument, accepting a Room type as input.
    The message template must have a mandatory {origin} and an optional {target} placeholders.
    origin and target parameters must be type Entity, with the AttributesComponent loaded.
    origin is mandatory, target is optional.

    The emitted message type is a string, the target is the client text field.
    """
    from core.src.world.builder import transport
    room = room or (origin.get_room() or await get_current_room(origin))
    listeners = await get_eligible_listeners_for_room(room)
    listeners = [
        listener for listener in listeners if listener.entity_id not in (
            origin and origin.entity_id, target and target.entity_id
        )
    ]
    if not listeners:
        return
    await batch_load_components((SystemComponent, 'connection'), PositionComponent, entities=listeners)
    futures = []
    for entity in listeners:
        position = entity.get_component(PositionComponent)
        if position.coord == room.position.coord and entity.get_component(SystemComponent).connection:
            # TODO - Evaluate VS entity memory
            futures.append(
                transport.send_message(
                    entity.get_component(SystemComponent).connection.value,
                    message_template.format(
                        origin=origin.get_component(AttributesComponent).keyword,
                        target=target and target.get_component(AttributesComponent).keyword
                    )
                )
            )
    await asyncio.gather(*futures)
Esempio n. 25
0
 async def _do_follow(self, follower_id: int, event: typing.Dict):
     current_followed_id = self._follow_by_follower.get(follower_id)
     if current_followed_id != event['entity']['id']:
         LOGGER.core.error('Error on follow system')
         return
     entity = await load_components(Entity(follower_id), SystemComponent, PositionComponent)
     if entity.get_component(PositionComponent).list_coordinates != event['from']:
         LOGGER.core.error('Error on follow system')
         return
     await do_move_entity(
         entity,
         Room(PositionComponent().set_list_coordinates(event['to'])),
         None,
         reason="movement",
         emit_message=False
     )
Esempio n. 26
0
async def ensure_same_position(self_entity: Entity, *entities: Entity) -> bool:
    """
    Ensures two or more entities are in the same position.
    Return a boolean.
    """
    assert self_entity.itsme
    self_pos = self_entity.get_component(PositionComponent)
    await batch_load_components(PositionComponent, entities=entities)

    for e in entities:
        position = e.get_component(PositionComponent)
        if position.coord and position.coord != self_pos.coord:
            return False
        elif position.parent_of and position.parent_of != self_entity.entity_id:
            return False
        elif not position.parent_of and not position.coord:
            LOGGER.core.error('Cannot determinate if an item is in the same position as previous declared')
            return False
    return True
Esempio n. 27
0
    def get_instance_of(self, name: str,
                        entity: Entity) -> typing.Optional[Entity]:
        e = Entity()
        data = self._local_copy.get(name)
        if not data:
            return

        system_component = SystemComponent()\
            .instance_of.set(data['libname'])\
            .created_at.set(int(time.time()))\
            .instance_by.set(entity.entity_id)

        e.set_for_update(system_component)
        for component in data['components']:
            comp_type = get_component_by_type(component)
            if comp_type.has_default:
                e.set_for_update(comp_type().activate())
            else:
                e.set_for_update(
                    comp_type(value=data['components'][component]))
        return e
Esempio n. 28
0
async def put(entity: Entity, keyword: str, target: str):
    await load_components(entity, PositionComponent, InventoryComponent)
    inventory = entity.get_component(InventoryComponent)
    items = await search_entities_in_container_by_keyword(inventory, keyword)
    target_entity = await search_entity_in_sight_by_keyword(
        entity, target, filter_by=InventoryComponent, include_self=False
    )
    if not target_entity:
        await emit_msg(entity, messages.target_not_found())
        return
    msgs_stack = get_stacker()
    items_to_drop = []
    for item in items:
        items_to_drop.append(
            move_entity_from_container(
                item,
                target=target_entity.get_component(InventoryComponent),
                current_owner=entity
            )
        )
    if not items_to_drop:
        await emit_msg(entity, messages.target_not_found())
        return
    msgs_stack.add(
        emit_sys_msg(entity, 'remove_items', messages.items_to_message(items_to_drop)),
        #emit_room_sys_msg(entity, 'add_items', messages.items_to_message(items_to_drop)) # todo event for container
    )
    if len(items_to_drop) == 1:
        msgs_stack.add(
            emit_msg(entity, messages.on_put_item(items[0], target_entity)),
            emit_room_msg(origin=entity, message_template=messages.on_entity_put_item(items[0], target_entity))
        )
    else:
        msgs_stack.add(
            emit_msg(entity, messages.on_put_multiple_items(target_entity)),
            emit_room_msg(origin=entity, message_template=messages.on_entity_put_multiple_items(target_entity))
        )
    if not await update_entities(entity, target_entity, *items_to_drop):
        await emit_msg(entity, messages.target_not_found())
        msgs_stack.cancel()
    else:
        await msgs_stack.execute()
Esempio n. 29
0
async def _create_instance(entity: Entity, parent_alias: str, *args):
    from core.src.world.builder import world_repository, library_repository
    instanced = library_repository.get_instance_of(parent_alias, entity)
    if not instanced:
        await emit_msg(entity,
                       'Cannot obtain instance of {}'.format(parent_alias))
        return
    if args:
        location = args[0]
        if location not in ('.', '@here'):
            await emit_msg(
                entity,
                'Error, location {} invalid (allowed location: ".")'.format(
                    location))
        await load_components(entity, PositionComponent)
        instanced.set_for_update(entity.get_component(PositionComponent))
    else:
        await emit_msg(entity,
                       'Inventory not implemented, please specify a location')
    await world_repository.save_entity(instanced)
    return instanced
Esempio n. 30
0
 def _check_bounds_for_update(pipeline: RedisLUAPipeline, entity: Entity):
     for bound in entity.bounds():
         assert bound.is_struct
         assert bound.bounds
         for k, bb in bound.bounds.items():
             for b in bb:
                 if isinstance(b, StructSubtypeListAction):
                     assert b.type == 'remove'
                     key = 'c:{}:zs:e:{}:{}'.format(bound.enum, entity.entity_id, k)
                     values = b.values
                     if len(values) == 1:
                         pipeline.allocate_value().zscan(key, cursor=0, match=values[0])
                         v, check = "[2][1]", str(values[0])
                     else:
                         inter_seed = pipeline.zprepareinter(key, values)
                         pipeline.allocate_value().zfetchinter(inter_seed)
                         v, check = "", values
                     pipeline.add_if_equal(check, value_selector=v)
                 else:
                     raise ValueError('Unknown bound')
             bound.remove_bounds()