tale_service.py (6313B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\taleclient\tale_service.py 2 from collections import OrderedDict 3 from carbon.common.script.sys.service import Service 4 from datetime import datetime, timedelta 5 from logging import getLogger 6 from taleclient.listener.listener_signals import on_started_notice, on_stopped_notice 7 from taleclient.listener.notice_listener import TalesNoticeListener 8 from talecommon.active_tale_thin import ActiveTaleThin 9 from talecommon.const import templateClass 10 from taleclient.active_tale import ActiveTale 11 from caching import Memoize 12 from signals import Signal 13 if False: 14 from typing import Dict, List 15 on_active_tale_added = Signal(signalName='on_active_tale_added') 16 on_active_tale_updated = Signal(signalName='on_active_tale_updated') 17 on_active_tale_removed = Signal(signalName='on_active_tale_removed') 18 _ACTIVE_TALES_CACHE_TTL = 600 19 logger = getLogger(__name__) 20 21 class TaleService(Service): 22 __guid__ = 'svc.tale' 23 __displayname__ = 'Tale Client Service' 24 __notifyevents__ = ['OnTaleData', 25 'OnTaleRemove', 26 'OnInfluenceUpdate', 27 'OnSessionChanged'] 28 __startupdependencies__ = ['publicGatewaySvc'] 29 30 def __init__(self): 31 super(TaleService, self).__init__() 32 self._notice_listener = TalesNoticeListener(sm.GetService('publicGatewaySvc')) 33 self._active_tales_in_system = OrderedDict() 34 self._active_tales_by_template = {} 35 logger.info('Tales - Tale service initialized.') 36 on_started_notice.connect(self._on_tale_started_notice) 37 on_stopped_notice.connect(self._on_tale_stopped_notice) 38 39 def __del__(self): 40 on_started_notice.disconnect(self._on_tale_started_notice) 41 on_stopped_notice.disconnect(self._on_tale_stopped_notice) 42 43 def OnSessionChanged(self, isremote, sess, change): 44 if 'solarsystemid2' in change or 'charid' in change: 45 self._remove_irrelevant_tales_in_system() 46 self._clear_active_tales_cache() 47 48 def OnTaleData(self, solarSystemID, data): 49 if solarSystemID != session.solarsystemid2: 50 return 51 for tale in data.itervalues(): 52 self._add_active_tale_in_system(tale) 53 54 def OnTaleRemove(self, taleID, templateClassID, templateID): 55 self._remove_active_tale_in_system(taleID) 56 57 def OnInfluenceUpdate(self, taleID, newInfluenceData): 58 if taleID in self._active_tales_in_system: 59 self._active_tales_in_system[taleID].influence = newInfluenceData.influence 60 on_active_tale_updated(taleID) 61 62 def get_active_tale_in_system(self, tale_id): 63 return self._active_tales_in_system.get(tale_id, None) 64 65 def get_active_world_event_tales_in_system(self): 66 return self._get_active_tales_in_system(templateClass.worldEvents) 67 68 def _get_active_tales_in_system(self, template_class_id): 69 return [ tale for tale in self._active_tales_in_system.itervalues() if tale.template_class_id == template_class_id ] 70 71 def _add_active_tale_in_system(self, tale): 72 if getattr(tale, 'objectiveChainID', None) is None: 73 return 74 if tale.taleID not in self._active_tales_in_system: 75 self._active_tales_in_system[tale.taleID] = ActiveTale(tale) 76 on_active_tale_added(tale.taleID) 77 sm.GetService('infoPanel').UpdateWorldEventsPanel() 78 else: 79 self._active_tales_in_system[tale.taleID].update(tale) 80 on_active_tale_updated(tale.taleID) 81 82 def _remove_active_tale_in_system(self, tale_id): 83 if tale_id not in self._active_tales_in_system: 84 return 85 tale = self._active_tales_in_system.pop(tale_id, None) 86 if tale: 87 tale.close() 88 on_active_tale_removed(tale.tale_id) 89 sm.GetService('infoPanel').UpdateWorldEventsPanel() 90 91 def _remove_irrelevant_tales_in_system(self): 92 for tale_id in self._active_tales_in_system.keys(): 93 if self._active_tales_in_system[tale_id].solar_system_id != session.solarsystemid2: 94 tale = self._active_tales_in_system.pop(tale_id, None) 95 if tale: 96 tale.close() 97 on_active_tale_removed(tale.tale_id) 98 99 sm.GetService('infoPanel').UpdateWorldEventsPanel() 100 101 def get_active_tales_by_template_id(self, template_id): 102 if template_id is None: 103 logger.warning('Tales - requesting active tales by template ID without a template ID') 104 return [] 105 if template_id not in self._active_tales_by_template: 106 logger.info('Tales - active tales for template %s cache does not exist, creating.' % template_id) 107 self._active_tales_by_template[template_id] = _TaleByTemplateCache(template_id) 108 if self._active_tales_by_template[template_id].is_expired(): 109 logger.info('Tales - active tales for template %s cache is expired, refreshing.' % template_id) 110 self._active_tales_by_template[template_id].tales = [ ActiveTaleThin(tale_id=raw_data['tale_id'], template_id=raw_data['template_id'], solar_system_id=raw_data['solar_system_id'], start_date=raw_data['start_date'], end_date=raw_data['end_date']) for raw_data in sm.RemoteSvc('taleMgr').get_active_tales_by_template(template_id) ] 111 return self._active_tales_by_template[template_id].tales 112 113 def _on_tale_started_notice(self, *args): 114 self._clear_active_tales_cache() 115 116 def _on_tale_stopped_notice(self, *args): 117 self._clear_active_tales_cache() 118 119 def _clear_active_tales_cache(self): 120 self._active_tales_by_template = {} 121 122 @Memoize(15) 123 def get_global_world_event_tales(self): 124 return sm.RemoteSvc('taleMgr').GetGlobalWorldEventTales() 125 126 127 class _TaleByTemplateCache(object): 128 129 def __init__(self, template_id): 130 self.template_id = template_id 131 self._tales = [] 132 self._timestamp = None 133 134 @property 135 def tales(self): 136 return self._tales 137 138 @tales.setter 139 def tales(self, value): 140 self._tales = value 141 self._timestamp = datetime.now() 142 143 def is_expired(self): 144 if self._timestamp is None: 145 return True 146 elapsed = datetime.now() - self._timestamp 147 return elapsed > timedelta(seconds=_ACTIVE_TALES_CACHE_TTL)