component.py (13705B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\cosmetics\common\ships\skins\static_data\component.py 2 from evetypes import TypeNotFoundException 3 import chroma 4 import logging 5 import sys 6 import evetypes 7 from itertoolsext.Enum import Enum 8 from cosmetics.common.ships.skins.static_data.ntc import ntc 9 from cosmetics.common.ships.skins.static_data.component_finish import get_finish_from_fsd 10 from cosmetics.common.ships.skins.live_data.component_license_type import ComponentLicenseType 11 from cosmetics.common.ships.skins.static_data.component_point_value import ComponentPointValuesTable 12 from inventorycommon.const import groupShipSkinDesignComponents 13 from localization import GetByMessageID 14 from fsdBuiltData.common.base import BuiltDataLoader 15 from cosmetics.common.ships.skins.static_data.component_category import get_category_from_fsd, ComponentCategory 16 from cosmetics.common.ships.skins.static_data.component_rarity import get_rarity_from_fsd, ComponentRarityLevel 17 from cosmetics.common.ships.skins.static_data.slot_name import SlotID 18 COMPONENT_ITEM_INFINITE_USES_GRANTED = -1 19 try: 20 import ship_skin_design_componentsLoader 21 except ImportError: 22 ship_skin_design_componentsLoader = None 23 24 try: 25 import ship_skin_design_components_post_processLoader 26 except ImportError: 27 ship_skin_design_components_post_processLoader = None 28 29 log = logging.getLogger(__name__) 30 31 class ComponentsPostProcessDataLoader(BuiltDataLoader): 32 __resBuiltFile__ = 'res:/staticdata/ship_skin_design_components_post_process.fsdbinary' 33 __clientAutobuildBuiltFile__ = 'eve/autobuild/staticData/client/ship_skin_design_components_post_process.fsdbinary' 34 __serverAutobuildBuiltFile__ = 'eve/autobuild/staticData/server/ship_skin_design_components_post_process.fsdbinary' 35 __loader__ = ship_skin_design_components_post_processLoader 36 37 @classmethod 38 def get_hex_color_by_id(cls, component_id): 39 components_post_process_data = cls.GetData() 40 if not components_post_process_data: 41 log.error('GetData() returned None in ComponentsPostProcessDataLoader.get_hex_color_by_id') 42 return 43 component_color_hex = components_post_process_data.get(component_id, None) 44 if component_color_hex is None: 45 log.error('component id %s not found in ComponentsPostProcessDataLoader' % component_id) 46 return component_color_hex 47 48 49 class ComponentsDataLoader(BuiltDataLoader): 50 __resBuiltFile__ = 'res:/staticdata/ship_skin_design_components.fsdbinary' 51 __clientAutobuildBuiltFile__ = 'eve/autobuild/staticData/client/ship_skin_design_components.fsdbinary' 52 __serverAutobuildBuiltFile__ = 'eve/autobuild/staticData/server/ship_skin_design_components.fsdbinary' 53 __loader__ = ship_skin_design_componentsLoader 54 _components_by_id = None 55 _is_initialized = False 56 57 @classmethod 58 def ReloadDataFromDisk(cls): 59 cls._components_by_id = None 60 cls._is_initialized = False 61 62 @classmethod 63 def get_component_data(cls, component_id): 64 cls._check_init_components_by_id() 65 return cls._components_by_id.get(component_id, None) 66 67 @classmethod 68 def get_components_data(cls, category_filter = None, slot_internal_name_filter = None): 69 cls._check_init_components_by_id() 70 result = {} 71 for component_id, component_data in cls._components_by_id.items(): 72 if (category_filter is None or component_data.category in category_filter) and (slot_internal_name_filter is None or slot_internal_name_filter not in component_data.disallowed_slot_ids): 73 result[component_id] = component_data 74 75 return result 76 77 @classmethod 78 def load_components_data(cls): 79 cls._check_init_components_by_id() 80 81 @classmethod 82 def _check_init_components_by_id(cls): 83 if cls._is_initialized: 84 return 85 log.info('SKIN COMPONENT LICENSES MANAGEMENT - Start loading component data') 86 cls._components_by_id = {} 87 components_data = ComponentsDataLoader.GetData() 88 if not components_data: 89 log.info('SKIN COMPONENT LICENSES MANAGEMENT - Component data unavailable, will try again later') 90 return 91 for component_id, component_data in components_data.items(): 92 cls._components_by_id[component_id] = ComponentData.build_from_fsd(component_id, component_data, ComponentPointValuesTable()) 93 94 cls._is_initialized = True 95 log.info('SKIN COMPONENT LICENSES MANAGEMENT - Finished loading component data') 96 97 @classmethod 98 def ReloadDataFromDisk(cls): 99 super(ComponentsDataLoader, cls).ReloadDataFromDisk() 100 cls._components_by_id = None 101 102 @classmethod 103 def get_component_for_component_type(cls, component_type_id): 104 try: 105 group_id = evetypes.GetGroupID(component_type_id) 106 except TypeNotFoundException: 107 return None 108 109 if group_id != groupShipSkinDesignComponents: 110 log.warning('type id %s must be of group %s to be matched to a ship skin component' % (component_type_id, groupShipSkinDesignComponents)) 111 components = cls.get_components_data() 112 for component_id, component_data in components.items(): 113 item_data = component_data.component_item_data_by_type_id.get(component_type_id) 114 if item_data: 115 return component_data 116 117 log.warning('could not match type id %s to any component id' % component_type_id) 118 119 @classmethod 120 def get_component_item_for_component_type(cls, component_type_id): 121 component_data = cls.get_component_for_component_type(component_type_id) 122 if component_data: 123 item_data = component_data.component_item_data_by_type_id.get(component_type_id) 124 return item_data 125 126 127 class ComponentData(object): 128 129 def __init__(self, component_id, internal_name, name_id, description_id, origin_event_id, category, rarity, finish, resource_file_path, icon_file_path, disallowed_slot_ids, associated_type_ids, sequence_binder_type_id, sequence_binder_required_amount, points_value, projection_type_uv, published): 130 self._color_shade_sort_index = sys.maxint 131 log.info('ComponentData init - component_id: {component_id} name_id: {name_id} icon_file_path: {icon_file_path}'.format(component_id=component_id, name_id=name_id, icon_file_path=icon_file_path)) 132 component_color_hex = ComponentsPostProcessDataLoader.get_hex_color_by_id(component_id) 133 if component_color_hex is None: 134 log.warning('None returned by get_hex_color_by_id for component_id: {component_id} name_id: {name_id} icon_file_path: {icon_file_path} ComponentData init - resource_file_path: {resource_file_path}'.format(component_id=component_id, name_id=name_id, resource_file_path=resource_file_path, icon_file_path=icon_file_path)) 135 else: 136 color_shade_name = ntc.shade_name_from_hex(component_color_hex) 137 color_order_list = ['Red', 138 'Orange', 139 'Yellow', 140 'Green', 141 'Blue', 142 'Violet', 143 'Brown', 144 'Black', 145 'Grey', 146 'White'] 147 self._color_shade_sort_index = color_order_list.index(color_shade_name) 148 apply_secondary_hue_sort = True 149 if apply_secondary_hue_sort: 150 hue, s, l = chroma.hex_to_hsl(component_color_hex) 151 self._color_shade_sort_index *= 1000 152 self._color_shade_sort_index += int(float(hue) * 360.0) 153 log.info('color_shade_name: {color_shade_name} color_shade_sort_index: {color_shade_sort_index} ComponentData init - component_id: {component_id} name_id: {name_id} resource_file_path: {resource_file_path}'.format(component_id=component_id, name_id=name_id, resource_file_path=resource_file_path, color_shade_name=color_shade_name, color_shade_sort_index=self._color_shade_sort_index)) 154 self._component_id = component_id 155 self._internal_name = internal_name 156 self._name_id = name_id 157 self._description_id = description_id 158 self._origin_event_id = origin_event_id 159 self._category = category 160 self._rarity = rarity 161 self._finish = finish 162 self._resource_file_path = resource_file_path 163 self._icon_file_path = icon_file_path 164 self._disallowed_slot_ids = disallowed_slot_ids 165 self._component_item_data_by_type_id = associated_type_ids 166 self._sequence_binder_type_id = sequence_binder_type_id 167 self._sequence_binder_required_amount = sequence_binder_required_amount 168 self._points_value = points_value 169 self._projection_type_uv = projection_type_uv 170 self._published = published 171 172 @property 173 def color_shade_sort_index(self): 174 return self._color_shade_sort_index 175 176 @property 177 def component_id(self): 178 return self._component_id 179 180 @property 181 def internal_name(self): 182 return self._internal_name 183 184 @property 185 def name(self): 186 return GetByMessageID(self._name_id) 187 188 @property 189 def description(self): 190 return GetByMessageID(self._description_id) 191 192 @property 193 def origin_event_name(self): 194 if self._origin_event_id: 195 return GetByMessageID(self._origin_event_id) 196 197 @property 198 def category(self): 199 return self._category 200 201 @property 202 def rarity(self): 203 return self._rarity 204 205 @property 206 def finish(self): 207 return self._finish 208 209 @property 210 def resource_file_path(self): 211 return self._resource_file_path 212 213 @property 214 def icon_file_path(self): 215 return self._icon_file_path 216 217 @property 218 def disallowed_slot_ids(self): 219 return self._disallowed_slot_ids 220 221 @property 222 def projection_type_uv(self): 223 return self._projection_type_uv 224 225 @property 226 def component_item_data_by_type_id(self): 227 return self._component_item_data_by_type_id 228 229 @property 230 def sequence_binder_type_id(self): 231 return self._sequence_binder_type_id 232 233 @property 234 def sequence_binder_required_amount(self): 235 return self._sequence_binder_required_amount 236 237 @property 238 def published(self): 239 return self._published 240 241 @property 242 def points_value(self): 243 return self._points_value 244 245 def get_license_type(self, type_id): 246 component_item = self.component_item_data_by_type_id.get(type_id, None) 247 if component_item: 248 return component_item.license_type 249 250 def get_item_type(self, license_type): 251 for type_id, component_item in self.component_item_data_by_type_id.items(): 252 if component_item.license_type == license_type: 253 return type_id 254 255 @staticmethod 256 def build_from_fsd(component_id, fsd_data, points_value_table): 257 internal_name = fsd_data.internal_name 258 name_id = fsd_data.name 259 description_id = fsd_data.description 260 origin_event_id = fsd_data.origin_event 261 category = get_category_from_fsd(fsd_data.category) 262 rarity = get_rarity_from_fsd(fsd_data.rarity) 263 finish = get_finish_from_fsd(fsd_data.finish) 264 resource_file_path = fsd_data.resource_file 265 icon_file_path = fsd_data.icon_file 266 disallowed_slot_ids = [ x for x in fsd_data.disallowed_slots ] 267 associated_type_ids = {x.type_id:ComponentItemData(component_id, category, x.type_id, x.license_uses_granted) for x in fsd_data.associated_type_ids} 268 sequence_binder_type_id = fsd_data.sequence_binder.item_type_id 269 sequence_binder_required_amount = fsd_data.sequence_binder.count 270 points_value = points_value_table.get_point_value(category, rarity) 271 projection_type_uv = [projection_type_from_fsd(fsd_data.projection_type_u), projection_type_from_fsd(fsd_data.projection_type_v)] 272 published = fsd_data.published 273 return ComponentData(component_id, internal_name, name_id, description_id, origin_event_id, category, rarity, finish, resource_file_path, icon_file_path, disallowed_slot_ids, associated_type_ids, sequence_binder_type_id, sequence_binder_required_amount, points_value, projection_type_uv, published) 274 275 276 class ComponentItemData(object): 277 278 def __init__(self, component_id, category, type_id, license_uses_granted): 279 self._component_id = component_id 280 self._category = category 281 self._type_id = type_id 282 self._license_uses_granted = license_uses_granted if license_uses_granted > 0 else COMPONENT_ITEM_INFINITE_USES_GRANTED 283 284 @property 285 def component_id(self): 286 return self._component_id 287 288 @property 289 def category(self): 290 return self._category 291 292 @property 293 def type_id(self): 294 return self._type_id 295 296 @property 297 def license_uses_granted(self): 298 return self._license_uses_granted 299 300 @property 301 def license_type(self): 302 if self._license_uses_granted == COMPONENT_ITEM_INFINITE_USES_GRANTED: 303 return ComponentLicenseType.UNLIMITED 304 else: 305 return ComponentLicenseType.LIMITED 306 307 308 @Enum 309 310 class PatternProjectionType(object): 311 CLAMP = 0 312 REPEAT = 1 313 BORDER = 2 314 315 316 _PROJECTION_TYPE_FSD_MAPPING = {'Clamp': PatternProjectionType.CLAMP, 317 'Repeat': PatternProjectionType.REPEAT, 318 'Border': PatternProjectionType.BORDER} 319 _PROJECTION_TYPE_TO_FSD_MAPPING = {PatternProjectionType.CLAMP: 'Clamp', 320 PatternProjectionType.REPEAT: 'Repeat', 321 PatternProjectionType.BORDER: 'Border'} 322 323 def projection_type_from_fsd(fsd_value): 324 return _PROJECTION_TYPE_FSD_MAPPING.get(fsd_value, None) 325 326 327 def projection_type_to_fsd(value): 328 return _PROJECTION_TYPE_TO_FSD_MAPPING.get(value, None)