Exemple #1
0
 async def get_rooms_on_y(self,
                          y: int,
                          from_x: int,
                          to_x: int,
                          z: int,
                          get_content=True):
     assert to_x > from_x
     redis = await self.redis()
     pipeline = redis.pipeline()
     if z:
         packed_coordinates = (self._pack_coords(x, y, z)
                               for x in range(from_x, to_x))
         pipeline.hmget(self.z_valued_rooms_data_key, *packed_coordinates)
     else:
         k = self._coords_to_int(from_x, y)
         pipeline.getrange(self.terrains_bitmap_key, k,
                           k + ((to_x - from_x) - 1))
     get_content and [
         self._get_room_content(pipeline, x, y, z)
         for x in range(from_x, to_x)
     ]
     response = []
     i = 0
     result = await pipeline.execute()
     if z:
         res = result[0]
         d = 0
         for key, value in res[0].items():
             terrain = int(value)
             response.append(
                 Room(
                     position=PositionComponent().set_list_coordinates(
                         [from_x + d, y, z]),
                     terrain=TerrainEnum(terrain),
                 ))
             d += 1
         for res in result[i + 1]:
             response[i].add_entity_ids(list(res))
     else:
         terrains = struct.unpack('B' * (to_x - from_x), result[0])
         for d in range(0, to_x - from_x):
             response.append(
                 Room(position=PositionComponent().set_list_coordinates(
                     [from_x + d, y, z]),
                      terrain=TerrainEnum(terrains[d]),
                      entity_ids=get_content
                      and [int(x) for x in result[d + 1]] or []))
     return response
 async def asyncio_test(self):
     sut = RedisMapRepository(get_redis_factory(RedisType.DATA))
     await (await sut.redis()).flushdb()
     max_x, max_y, max_z = 500, 500, 1
     sut.max_y = max_y
     sut.max_x = max_x
     start = time.time()
     i = 0
     print('\nBaking {}x{} map'.format(max_x, max_y))
     for x in range(max_x, -1, -1):
         roomz = OrderedDict()
         for y in range(max_y, -1, -1):
             for z in range(0, max_z):
                 i += 1
                 position = PositionComponent(
                     coord='{},{},{}'.format(x, y, z))
                 roomz['{}.{}.{}'.format(x, y, z)] = Room(
                     position=position,
                     terrain=random.choice(
                         [TerrainEnum.WALL_OF_BRICKS, TerrainEnum.PATH]),
                 )
         print(i, ' rooms saved')
         await sut.set_rooms(*roomz.values())
     print('\n{}x{} map baked in {}'.format(max_x, max_y,
                                            time.time() - start))
     start = time.time()
     print('\nFetching {}x{} map'.format(max_x, max_y))
     tot = 0
     for x in range(0, max_x):
         res = await sut.get_rooms(*(PositionComponent(
             coord='{},{},{}'.format(x, y, 0)) for y in range(0, max_y)))
         tot += len(res)
     print('\n{}x{} map fetched in {} - total: {}'.format(
         max_x, max_y,
         time.time() - start, tot))
Exemple #3
0
    async def get_room(self,
                       position: PositionComponent,
                       populate=True) -> typing.Optional[Room]:
        if (self.min_y > position.y) or (self.max_y < position.y):
            raise exceptions.RoomError
        if (self.min_x > position.x) or (self.max_x < position.x):
            raise exceptions.RoomError

        redis = await self.redis()
        pipeline = redis.pipeline()
        if position.z:
            pipeline.hget(
                self.z_valued_rooms_data_key,
                '{}.{}.{}'.format(position.x, position.y, position.z),
            )
        else:
            k = self._coords_to_int(position.x, position.y)
            pipeline.getrange(self.terrains_bitmap_key, k, k)
        populate and self._get_room_content(pipeline, position.x, position.y,
                                            position.z)
        result = await pipeline.execute()
        if not result or not result[0]:
            LOGGER.core.error('Room Error. Request: %s, Result: %s', position,
                              result)
            raise exceptions.RoomError
        if position.z:
            terrain = int(result[0])
        else:
            terrain = int(struct.unpack('B', result[0])[0])
        content = populate and [int(x) for x in result[1]] or []

        return Room(position=position,
                    terrain=TerrainEnum(terrain),
                    entity_ids=content)
Exemple #4
0
 async def get_rooms(self, *positions: PositionComponent, get_content=True):
     redis = await self.redis()
     pipeline = redis.pipeline()
     for position in positions:
         if position.z:
             pipeline.hget(
                 self.z_valued_rooms_data_key,
                 '{}.{}.{}'.format(position.x, position.y, position.z))
         else:
             k = self._coords_to_int(position.x, position.y)
             pipeline.getrange(self.terrains_bitmap_key, k, k)
         get_content and self._get_room_content(pipeline, position.x,
                                                position.y, position.z)
     result = await pipeline.execute()
     i = 0
     response = []
     for position in positions:
         if position.z:
             terrain = int(result[i])
         else:
             terrain = int(struct.unpack('B', result[i])[0])
         i += 1
         if get_content:
             content = [int(x) for x in result[i]]
             i += 1
         else:
             content = []
         response.append(
             Room(position=position,
                  terrain=TerrainEnum(terrain),
                  entity_ids=content))
     return response
Exemple #5
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
Exemple #6
0
 async def do(self) -> bool:
     from core.src.world.actions.movement.move import do_move_entity
     if not self.entity.get_room():
         position = self.entity.get_component(PositionComponent)
         assert position
         self.entity.set_room(Room(PositionComponent))
     if not self.target_room:
         self.target_room = await get_room_at_direction(self.entity,
                                                        self.direction,
                                                        populate=False)
     if not await self.target_room.walkable_by(self.entity):
         new_target = self.escape_corners and await self.find_escape()
         if new_target:
             self.target_room = new_target
         else:
             await emit_msg(self.entity, messages.invalid_direction())
             return False
     await do_move_entity(self.entity,
                          self.target_room,
                          self.direction,
                          "movement",
                          self_emit_message=self._sem)
     self._sem = False
     self.target_room = None
     return True
def parse_lines(lines):
    lines = [l.strip() for l in lines]
    max_y = len(lines) - 1
    max_x = max([len(line) for line in lines]) - 1
    rooms = []
    for y in range(max_y, -1, -1):
        for x in range(0, max_x + 1):
            room_enum = terrains[lines[y][x]]
            if room_enum:
                rooms.append(
                    Room(position=PositionComponent().set_list_coordinates(
                        [x, max_y - y, 0]),
                         terrain=room_enum))
    return rooms
Exemple #8
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
     )
    async def asyncio_test(self):
        sut = RedisMapRepository(get_redis_factory(RedisType.DATA))
        await (await sut.redis()).flushdb()
        max_x, max_y = 50, 50
        sut.max_y = max_y
        sut.max_x = max_x
        start = time.time()
        print('\nBaking {}x{} map'.format(max_x, max_y))
        roomz = OrderedDict()
        for x in range(0, max_x):
            for y in range(0, max_y):
                position = PositionComponent(coord='{},{},{}'.format(x, y, 0))
                roomz['{}.{}.{}'.format(x, y, 0)] = Room(
                    position=position,
                    terrain=random.choice(
                        [TerrainEnum.WALL_OF_BRICKS, TerrainEnum.PATH]))
        await sut.set_rooms(*roomz.values())
        print('\n{}x{} map baked in {}'.format(max_x, max_y,
                                               time.time() - start))

        from_x, to_x = 0, 9
        for yy in range(0, 210, 10):
            futures = [
                sut.get_rooms_on_y(0, from_x, to_x, 0) for _ in range(0, yy)
            ]
            s = time.time()
            res = await asyncio.gather(*futures)
            print('Get line of {} rooms. Concurrency: '.format(to_x - from_x),
                  yy, ' users. Time: {:.8f}'.format(time.time() - s))
            for r in res:
                for req in range(0, to_x):
                    k = '{}.{}.{}'.format(from_x + req, 0, 0)
                    self.assertEqual([
                        r[req].position.x, r[req].position.y, r[req].position.z
                    ], [
                        roomz[k].position.x, roomz[k].position.y,
                        roomz[k].position.z
                    ])
    async def async_test(self):
        sut = RedisMapRepository(get_redis_factory(RedisType.DATA))
        await (await sut.redis()).flushdb()
        futures = []
        d = {}
        i = 0
        max_x, max_y, max_z = 25, 25, 5
        sut.max_y = max_y
        sut.max_x = max_x
        start = time.time()
        for x in range(0, max_x):
            for y in range(0, max_y):
                for z in range(0, max_z):
                    i += 1
                    d['{}.{}.{}'.format(x, y, z)] = [
                        random.randint(0, 65530),
                        random.randint(0, 65530)
                    ]
                    futures.append(
                        sut.set_room(
                            Room(position=PositionComponent(
                                coord='{},{},{}'.format(x, y, z)),
                                 terrain=TerrainEnum.WALL_OF_BRICKS)))
        await asyncio.gather(*futures)
        for x in range(0, max_x):
            for y in range(0, max_y):
                for z in range(0, max_z):
                    room = await sut.get_room(
                        PositionComponent(coord='{},{},{}'.format(x, y, z)))
                    self.assertEqual(
                        [room.position.x, room.position.y, room.position.z],
                        [x, y, z])
        print(
            '\n', i,
            ' rooms tested NO pipeline in {:.10f}'.format(time.time() - start))

        await (await sut.redis()).flushdb()
        _start = time.time()
        roomz = OrderedDict()
        positions = []
        for x in range(0, max_x):
            for y in range(0, max_y):
                for z in range(0, max_z):
                    position = PositionComponent(
                        coord='{},{},{}'.format(x, y, z))
                    positions.append(position)
                    roomz['{}.{}.{}'.format(x, y, z)] = Room(
                        position=position,
                        terrain=TerrainEnum.WALL_OF_BRICKS,
                    )
        await sut.set_rooms(*roomz.values())
        rooms = await sut.get_rooms(*positions)
        for i, room in enumerate(rooms):
            self.assertEqual([
                room.position.x,
                room.position.y,
                room.position.z,
            ], [
                positions[i].x,
                positions[i].y,
                positions[i].z,
            ])
        print(
            '\n', i + 1,
            ' rooms tested WITH pipeline in {:.10f}'.format(time.time() -
                                                            _start))

        positions = []
        i = 0
        for x in range(0, 9):
            for y in range(0, 9):
                positions.append(
                    PositionComponent(coord='{},{},{}'.format(x, y, 0)))
                i += 1
        print('\n Starting benchmarks: \n')
        for x in range(1, 110, 10):
            futures = [sut.get_rooms(*positions) for _ in range(0, x)]
            s = time.time()
            await asyncio.gather(*futures)
            print('Rooms: ', i, '. Concurrency: ', x,
                  ' users. Time: {:.8f}'.format(time.time() - s))

        positions = []
        i = 0
        for x in range(0, 9):
            y = 1
            positions.append(
                PositionComponent(coord='{},{},{}'.format(x, y, 0)))
            i += 1

        for x in range(1, 110, 10):
            futures = [sut.get_rooms(*positions) for _ in range(0, x)]
            s = time.time()
            await asyncio.gather(*futures)
            print('Rooms: ', i, '. Concurrency: ', x,
                  ' users. Time: {:.8f}'.format(time.time() - s))