Beispiel #1
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
Beispiel #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)
Beispiel #3
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
Beispiel #4
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
Beispiel #5
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)
Beispiel #6
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(),
        )
Beispiel #7
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
        }))
Beispiel #8
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
Beispiel #9
0
async def disconnect_entity(entity: Entity, msg=True):
    from core.src.world.builder import map_repository
    from core.src.world.builder import websocket_channels_service
    from core.src.world.builder import cmds_observer
    events_publisher = get_events_publisher()
    await load_components(entity, PositionComponent)
    listeners = await get_eligible_listeners_for_area(
        entity.get_component(PositionComponent))
    await events_publisher.on_entity_disappear_position(
        entity, entity.get_component(PositionComponent), "disconnect",
        listeners)
    msg and await emit_sys_msg(entity, "event", {"event": "quit"})
    current_channel_id = entity.get_component(SystemComponent).connection.value
    entity.set_for_update(SystemComponent().connection.set(""))
    if await update_entities(entity):
        await map_repository.remove_entity_from_map(
            entity.entity_id, entity.get_component(PositionComponent))
        await websocket_channels_service.close_namespace_for_entity_id(
            entity.entity_id)
        cmds_observer.close_channel(current_channel_id)
Beispiel #10
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)
Beispiel #11
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)
Beispiel #12
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()
Beispiel #13
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)
Beispiel #14
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))
Beispiel #15
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
Beispiel #16
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()
Beispiel #17
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
Beispiel #18
0
async def pick(entity: Entity, *arguments):
    keyword = arguments[0]
    if len(arguments) == 1:
        room = await get_current_room(entity)
        items_to_pick = await search_entities_in_room_by_keyword(
            room,
            keyword,
            filter_by=(AttributesComponent, 'collectible', True))
        container_entity = None
    elif len(arguments) == 2:
        container_keyword = arguments[1]
        container_entity = await search_entity_in_sight_by_keyword(
            entity,
            container_keyword,
            filter_by=InventoryComponent,
            include_self=False)
        await load_components(container_entity, InventoryComponent)
        if not container_entity:
            await emit_msg(entity, messages.target_not_in_room())
            return
        container_inventory = container_entity.get_component(
            InventoryComponent)
        items_to_pick = await search_entities_in_container_by_keyword(
            container_inventory, keyword)
    else:
        raise ValueError('max 2 arguments')
    if not items_to_pick:
        await emit_msg(entity, messages.target_not_in_room())
        return

    await load_components(entity, InventoryComponent)
    inventory = entity.get_component(InventoryComponent)
    for item in items_to_pick:
        move_entity_from_container(item,
                                   target=inventory,
                                   current_owner=container_entity)
    msgs_stack = get_stacker()
    if len(items_to_pick) == 1:
        if container_entity:
            # SINGLE ITEM FOUND IN CONTAINER
            msgs_stack.add(
                emit_msg(
                    entity,
                    messages.item_picked_from_container(
                        items_to_pick[0], container_entity)),
                emit_room_msg(origin=entity,
                              message_template=messages.
                              entity_picked_item_from_container(
                                  items_to_pick[0], container_entity)),
            )
        else:
            # SINGLE ITEM FOUND IN ROOM
            msgs_stack.add(
                emit_msg(entity, messages.item_picked(items_to_pick[0])),
                emit_room_msg(origin=entity,
                              message_template=messages.entity_picked_item(
                                  items_to_pick[0])),
            )
    else:
        if container_entity:
            # MULTIPLE ITEMS FOUND IN CONTAINER
            msgs_stack.add(
                emit_msg(
                    entity,
                    messages.picked_multiple_items_from_container(
                        container_entity)),
                emit_room_msg(origin=entity,
                              message_template=messages.
                              entity_picked_multiple_items_from_container(
                                  container_entity)),
            )
        else:
            # MULTIPLE ITEMS FOUND IN ROOM
            msgs_stack.add(
                emit_msg(entity, messages.picked_multiple_items()),
                emit_room_msg(
                    origin=entity,
                    message_template=messages.entity_picked_multiple_items()),
            )
    if items_to_pick:
        msgs_stack.add(
            emit_sys_msg(entity, 'add_items',
                         messages.items_to_message(items_to_pick)), )
        if not container_entity:
            msgs_stack.add(
                emit_room_sys_msg(entity, 'remove_items',
                                  messages.items_to_message(items_to_pick)))
        if not await update_entities(
                entity, *items_to_pick,
                *(container_entity and (container_entity, ) or ())):
            await emit_msg(entity, messages.cannot_pick_item())
            msgs_stack.cancel()
        else:
            await msgs_stack.execute()
 async def subscribe_events(self, entity: Entity):
     connection = entity.get_component(SystemComponent).connection
     assert connection.value
     self._transports_by_entity_id[entity.entity_id] = connection.value
     await asyncio.gather(self._subscribe_entity(entity))
Beispiel #20
0
async def inventory(entity: Entity):
    await load_components(entity, PositionComponent, InventoryComponent)
    inventory = entity.get_component(InventoryComponent)
    items = await search_entities_in_container_by_keyword(inventory, '*')
    await emit_sys_msg(entity, 'inventory', messages.items_to_message(items))
Beispiel #21
0
 def on_drop_item(self, item: Entity):
     return 'Posi {}'.format(
         item.get_component(AttributesComponent).keyword)
Beispiel #22
0
 def on_entity_drop_item(self, item: Entity):
     return '{origin} posa a terra %s' % item.get_component(
         AttributesComponent).keyword
Beispiel #23
0
 def item_picked(self, item: Entity):
     return 'raccogli {}'.format(
         item.get_component(AttributesComponent).keyword)
Beispiel #24
0
 def entity_picked_item(self, item: Entity):
     return '{origin} raccoglie %s' % item.get_component(
         AttributesComponent).keyword