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)
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)
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?!')
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)
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)
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
async def emit_msg(entity, message: str): from core.src.world.builder import transport from core.src.world.builder import world_repository if entity.itsme: connection_id = entity.get_component(SystemComponent).connection.value assert connection_id await transport.send_message(connection_id, message) return True else: if not entity.get_component(SystemComponent) or not entity.get_component(SystemComponent).connection: components_data = await world_repository.read_struct_components_for_entity( entity.entity_id, (SystemComponent, 'connection') ) connection_id = components_data[SystemComponent.enum].connection.value if connection_id: entity.set_component(SystemComponent().connection.set(connection_id)) await transport.send_message( entity.get_component(SystemComponent).connection, message ) return True return False
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))
async def bootstrap_subscribes(self, data: typing.List[typing.Dict]): for en in data: await self.subscribe_events( Entity(en['entity_id']).set_component( SystemComponent(connection=en['channel_id'])))
def get_follow_target(self, follower_id: int): response = self._follow_by_follower.get(follower_id) return response and Entity(response).set_component(SystemComponent(receive_events=True))