From aa4e17c84606b6338dbecda184875d4bbb6863d4 Mon Sep 17 00:00:00 2001 From: A_D Date: Wed, 30 Jun 2021 14:07:16 +0200 Subject: [PATCH 01/13] Add support for new fields on LoadGame These are the same as the ones on FileHeader, but it wont hurt to update them here anyway, if they exist. Likely they wont have changed, but just in case --- monitor.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/monitor.py b/monitor.py index d7471381..679d4921 100644 --- a/monitor.py +++ b/monitor.py @@ -20,6 +20,7 @@ if TYPE_CHECKING: import util_ships from config import config +from dashboard import dashboard from edmc_data import edmc_suit_shortnames, edmc_suit_symbol_localised from EDMCLogging import get_main_logger @@ -517,6 +518,13 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.live = True # First event in 3.0 elif event_type == 'loadgame': + # Odyssey Release Update 5 + self.state['GameLanguage'] = entry.get('language', self.state['GameLanguage']) + self.state['GameVersion'] = entry.get('gameversion', self.state['GameVersion']) + self.state['GameBuild'] = entry.get('build', self.state['GameBuild']) + self.version = self.state['GameVersion'] # Update this just in case things above changed. + self.is_beta = any(v in str(self.version).lower() for v in ('alpha', 'beta')) + # alpha4 # Odyssey: bool self.cmdr = entry['Commander'] From 1a3dad34b76ab3727a59b26a44488ffcef6f6574 Mon Sep 17 00:00:00 2001 From: A_D Date: Wed, 30 Jun 2021 14:23:25 +0200 Subject: [PATCH 02/13] Add support for SuitLoadout related added info This is mostly classes and mods for weapons, and classes for suits. I did not do any updating passed what we already did, I simply added the fields where needed. This means that if our tracking is incorrect it will still be incorrect, but full on tracking will wait for OO based state storage to prevent whoopsies and other silliness. --- monitor.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/monitor.py b/monitor.py index 679d4921..e0ef8786 100644 --- a/monitor.py +++ b/monitor.py @@ -1118,6 +1118,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below 'edmcName': self.suit_sane_name(loc_name), 'id': None, # Is this an FDev ID for suit type ? 'suitId': entry['SuitID'], + 'mods': entry['SuitMods'], # Suits can (rarely) be bought with modules installed 'slots': [], } @@ -1183,6 +1184,8 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below 'id': None, 'weaponrackId': entry['SuitModuleID'], 'locDescription': '', + 'class': entry['Class'], + 'mods': entry['WeaponMods'] } except KeyError: @@ -1657,6 +1660,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below 'locName': suitname, 'suitId': entry['SuitID'], 'name': entry['SuitName'], + 'mods': entry['SuitMods'] } suitloadout_slotid = self.suit_loadout_id_from_loadoutid(entry['LoadoutID']) @@ -2105,6 +2109,8 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below 'weaponrackId': loadout_slots[s]['SuitModuleID'], 'locName': loadout_slots[s].get('ModuleName_Localised', loadout_slots[s]['ModuleName']), 'locDescription': '', + 'class': loadout_slots[s]['Class'], + 'mods': loadout_slots[s]['WeaponMods'], } return slots From e11193110f2443ac2c0629e7d1b65074bb89651f Mon Sep 17 00:00:00 2001 From: A_D Date: Wed, 30 Jun 2021 14:26:45 +0200 Subject: [PATCH 03/13] removed dashboard import --- monitor.py | 1 - 1 file changed, 1 deletion(-) diff --git a/monitor.py b/monitor.py index e0ef8786..3e893835 100644 --- a/monitor.py +++ b/monitor.py @@ -20,7 +20,6 @@ if TYPE_CHECKING: import util_ships from config import config -from dashboard import dashboard from edmc_data import edmc_suit_shortnames, edmc_suit_symbol_localised from EDMCLogging import get_main_logger From 67df2efc8a496b4914eacb1b044db5992e339a42 Mon Sep 17 00:00:00 2001 From: A_D Date: Thu, 1 Jul 2021 12:27:15 +0200 Subject: [PATCH 04/13] DRY-ed setting version info Also removed some uneeded type ignores --- monitor.py | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/monitor.py b/monitor.py index 3e893835..b01e6bf1 100644 --- a/monitor.py +++ b/monitor.py @@ -182,9 +182,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below if journal_dir == '' or journal_dir is None: journal_dir = config.default_journal_dir - # TODO(A_D): this is ignored for type checking due to all the different types config.get returns - # When that is refactored, remove the magic comment - logdir = expanduser(journal_dir) # type: ignore # config is weird + logdir = expanduser(journal_dir) if not logdir or not isdir(logdir): logger.error(f'Journal Directory is invalid: "{logdir}"') @@ -201,11 +199,11 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below # Do this before setting up the observer in case the journal directory has gone away try: # TODO: This should be replaced with something specific ONLY wrapping listdir logfiles = sorted( - (x for x in listdir(self.currentdir) if self._RE_LOGFILE.search(x)), # type: ignore # config is weird + (x for x in listdir(self.currentdir) if self._RE_LOGFILE.search(x)), key=lambda x: x.split('.')[1:] ) - self.logfile = join(self.currentdir, logfiles[-1]) if logfiles else None # type: ignore # config is weird + self.logfile = join(self.currentdir, logfiles[-1]) if logfiles else None except Exception: logger.exception('Failed to find latest logfile') @@ -492,8 +490,6 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below event_type = entry['event'].lower() if event_type == 'fileheader': self.live = False - self.version = entry['gameversion'] - self.is_beta = any(v in entry['gameversion'].lower() for v in ('alpha', 'beta')) self.cmdr = None self.mode = None @@ -508,21 +504,16 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.systemaddress = None self.started = None self.__init_state() - # In self.state as well, as that's what plugins get - self.state['GameLanguage'] = entry['language'] - self.state['GameVersion'] = entry['gameversion'] - self.state['GameBuild'] = entry['build'] + + # Do this AFTER __init_state() lest our nice new state entries be None + self.populate_version_info(entry) elif event_type == 'commander': self.live = True # First event in 3.0 elif event_type == 'loadgame': # Odyssey Release Update 5 - self.state['GameLanguage'] = entry.get('language', self.state['GameLanguage']) - self.state['GameVersion'] = entry.get('gameversion', self.state['GameVersion']) - self.state['GameBuild'] = entry.get('build', self.state['GameBuild']) - self.version = self.state['GameVersion'] # Update this just in case things above changed. - self.is_beta = any(v in str(self.version).lower() for v in ('alpha', 'beta')) + self.populate_version_info(entry, suppress=True) # alpha4 # Odyssey: bool @@ -1583,6 +1574,22 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below logger.debug(f'Invalid journal entry:\n{line!r}\n', exc_info=ex) return {'event': None} + def populate_version_info(self, entry: MutableMapping[str, str], suppress: bool = False): + """ + Update game version information stored locally. + + :param entry: Either a Fileheader or LoadGame event + """ + try: + self.state['GameLanguage'] = entry['language'] + self.state['GameVersion'] = entry['gameversion'] + self.state['GameBuild'] = entry['build'] + self.version = self.state['GameVersion'] + self.is_beta = any(v in self.version.lower() for v in ('alpha', 'beta')) + except KeyError: + if not suppress: + raise + def backpack_set_empty(self): """Set the BackPack contents to be empty.""" self.state['BackPack']['Component'] = defaultdict(int) From d63b6ad782ba022bb1c1d5c5995d19a7813a13a3 Mon Sep 17 00:00:00 2001 From: A_D Date: Thu, 1 Jul 2021 12:47:07 +0200 Subject: [PATCH 05/13] removed suits["slots"] (for now) --- monitor.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/monitor.py b/monitor.py index b01e6bf1..6392f2c0 100644 --- a/monitor.py +++ b/monitor.py @@ -1109,7 +1109,6 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below 'id': None, # Is this an FDev ID for suit type ? 'suitId': entry['SuitID'], 'mods': entry['SuitMods'], # Suits can (rarely) be bought with modules installed - 'slots': [], } # update credits @@ -1682,7 +1681,6 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below # Now add in the extra fields for new_suit to be a 'full' Suit structure suit['id'] = suit.get('id') # Not available in 4.0.0.100 journal event - suit['slots'] = new_loadout['slots'] # 'slots', not 'Modules', to match CAPI # Ensure the suit is in self.state['Suits'] self.state['Suits'][f"{suitid}"] = suit From 1e691d306ee80489f8113031963b58aea8459b5a Mon Sep 17 00:00:00 2001 From: A_D Date: Sat, 3 Jul 2021 13:22:39 +0200 Subject: [PATCH 06/13] Added support for resupply event its a reskinned backpack, so thats how its being handled --- monitor.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/monitor.py b/monitor.py index 6392f2c0..f45910c2 100644 --- a/monitor.py +++ b/monitor.py @@ -912,7 +912,11 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below logger.warning(f'We have a BackPackMaterials event, defunct since > 4.0.0.102 ?:\n{entry}\n') pass - elif event_type == 'backpack': + elif event_type in ('backpack', 'resupply'): + # as of v4.0.0.600, a `resupply` event is dropped when resupplying your suit at your ship. + # This event writes the same data as a backpack event. It will also be followed by a ShipLocker + # but that follows normal behaviour in its handler. + # TODO: v31 doc says this is`backpack.json` ... but Howard Chalkley # said it's `Backpack.json` backpack_file = pathlib.Path(str(self.currentdir)) / 'Backpack.json' From 6a296d4920592589d0fd01acdb13fc530d26093c Mon Sep 17 00:00:00 2001 From: A_D Date: Sat, 3 Jul 2021 15:48:25 +0200 Subject: [PATCH 07/13] fixed inara per-event killswitch doing nothing --- plugins/inara.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/inara.py b/plugins/inara.py index 768aab95..ea46f9ce 100644 --- a/plugins/inara.py +++ b/plugins/inara.py @@ -341,6 +341,8 @@ def journal_entry( # noqa: C901, CCR001 elif (ks := killswitch.get_disabled(f'plugins.inara.journal.event.{entry["event"]}')).disabled: logger.warning(f'event {entry["event"]} processing has been disabled via killswitch: {ks.reason}') + # this can and WILL break state, but if we're concerned about it sending bad data, we'd disable globally anyway + return '' this.on_foot = state['OnFoot'] event_name: str = entry['event'] From edbf1263a923faf70d4e2b7a20410cc0a3c5431b Mon Sep 17 00:00:00 2001 From: A_D Date: Sat, 3 Jul 2021 17:14:25 +0200 Subject: [PATCH 08/13] Dont store version on loadgame, its content is faulty --- monitor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/monitor.py b/monitor.py index f45910c2..e025aa06 100644 --- a/monitor.py +++ b/monitor.py @@ -512,8 +512,8 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below self.live = True # First event in 3.0 elif event_type == 'loadgame': - # Odyssey Release Update 5 - self.populate_version_info(entry, suppress=True) + # Odyssey Release Update 5 -- This contains data that doesn't match the format used in FileHeader above + # self.populate_version_info(entry, suppress=True) # alpha4 # Odyssey: bool From dec2e07ce0533abe4e78fec7b5cfe8455e12897c Mon Sep 17 00:00:00 2001 From: A_D Date: Sat, 3 Jul 2021 17:18:47 +0200 Subject: [PATCH 09/13] revert previous commit, handle \ in lang names --- edmc_data.py | 5 +++++ monitor.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/edmc_data.py b/edmc_data.py index ff746196..8098bd7e 100644 --- a/edmc_data.py +++ b/edmc_data.py @@ -571,6 +571,11 @@ edmc_suit_symbol_localised = { }, } +# 4.0.0.600 Update 5 introduced duplicates of `fileheader` keys into `LoadGame`, +# but the GameLanguage in the latter has doubled up the `\`, so cater for either. +for lang, new_lang in map(lambda k: (k, k.replace('\\', r'\\')), list(edmc_suit_symbol_localised.keys())): + edmc_suit_symbol_localised[new_lang] = edmc_suit_symbol_localised[lang] + # Local webserver for debugging. See implementation in debug_webserver.py DEBUG_WEBSERVER_HOST = '127.0.0.1' DEBUG_WEBSERVER_PORT = 9090 diff --git a/monitor.py b/monitor.py index e025aa06..9eefafee 100644 --- a/monitor.py +++ b/monitor.py @@ -513,7 +513,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below elif event_type == 'loadgame': # Odyssey Release Update 5 -- This contains data that doesn't match the format used in FileHeader above - # self.populate_version_info(entry, suppress=True) + self.populate_version_info(entry, suppress=True) # alpha4 # Odyssey: bool From 3bde283048273fcbf3f689e44541e47d3e7fbb60 Mon Sep 17 00:00:00 2001 From: A_D Date: Sat, 3 Jul 2021 17:29:10 +0200 Subject: [PATCH 10/13] make comments congruent with convention from contributing commandment --- edmc_data.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/edmc_data.py b/edmc_data.py index 8098bd7e..3ba08ddc 100644 --- a/edmc_data.py +++ b/edmc_data.py @@ -571,8 +571,9 @@ edmc_suit_symbol_localised = { }, } -# 4.0.0.600 Update 5 introduced duplicates of `fileheader` keys into `LoadGame`, -# but the GameLanguage in the latter has doubled up the `\`, so cater for either. +# WORKAROUND 2021-07-03 | 4.0.0.600 Update 5: duplicates of `fileheader` keys in `LoadGame`, +# but the GameLanguage in the latter has doubled up the `\`, so cater for either here. +# This is only run once when this file is imported by something, no runtime cost or repeated expansions will occur for lang, new_lang in map(lambda k: (k, k.replace('\\', r'\\')), list(edmc_suit_symbol_localised.keys())): edmc_suit_symbol_localised[new_lang] = edmc_suit_symbol_localised[lang] From c898a9226a0c71a1a9dd8575d1139e743d34cc30 Mon Sep 17 00:00:00 2001 From: A_D Date: Mon, 5 Jul 2021 11:12:06 +0200 Subject: [PATCH 11/13] added forwardslash to additional keys --- edmc_data.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/edmc_data.py b/edmc_data.py index 3ba08ddc..fed0f135 100644 --- a/edmc_data.py +++ b/edmc_data.py @@ -574,8 +574,14 @@ edmc_suit_symbol_localised = { # WORKAROUND 2021-07-03 | 4.0.0.600 Update 5: duplicates of `fileheader` keys in `LoadGame`, # but the GameLanguage in the latter has doubled up the `\`, so cater for either here. # This is only run once when this file is imported by something, no runtime cost or repeated expansions will occur -for lang, new_lang in map(lambda k: (k, k.replace('\\', r'\\')), list(edmc_suit_symbol_localised.keys())): +__keys = list(edmc_suit_symbol_localised.keys()) +for lang in __keys: + new_lang = lang.replace('\\', r'\\') + new_lang_2 = lang.replace('\\', '/') + edmc_suit_symbol_localised[new_lang] = edmc_suit_symbol_localised[lang] + edmc_suit_symbol_localised[new_lang_2] = edmc_suit_symbol_localised[lang] + # Local webserver for debugging. See implementation in debug_webserver.py DEBUG_WEBSERVER_HOST = '127.0.0.1' From 4e7366bee0b19ac387398c6d2eed273885eead6b Mon Sep 17 00:00:00 2001 From: A_D Date: Mon, 5 Jul 2021 11:17:19 +0200 Subject: [PATCH 12/13] updated comment --- edmc_data.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/edmc_data.py b/edmc_data.py index fed0f135..fe1c63b2 100644 --- a/edmc_data.py +++ b/edmc_data.py @@ -573,6 +573,8 @@ edmc_suit_symbol_localised = { # WORKAROUND 2021-07-03 | 4.0.0.600 Update 5: duplicates of `fileheader` keys in `LoadGame`, # but the GameLanguage in the latter has doubled up the `\`, so cater for either here. +# This is sourced from what the game is passed by the launcher, caveat emptor. It was mentioned that / is also +# an option # This is only run once when this file is imported by something, no runtime cost or repeated expansions will occur __keys = list(edmc_suit_symbol_localised.keys()) for lang in __keys: From 7c78b4009038ce115f897c9ac66004f6b028005d Mon Sep 17 00:00:00 2001 From: A_D Date: Wed, 7 Jul 2021 11:02:11 +0200 Subject: [PATCH 13/13] always update with journal data --- monitor.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/monitor.py b/monitor.py index 9eefafee..ba6a6b8b 100644 --- a/monitor.py +++ b/monitor.py @@ -1667,11 +1667,14 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below suit = { 'edmcName': edmc_suitname, 'locName': suitname, - 'suitId': entry['SuitID'], - 'name': entry['SuitName'], - 'mods': entry['SuitMods'] } + # Overwrite with latest data, just in case, as this can be from CAPI which may or may not have had + # all the data we wanted + suit['suitId'] = entry['SuitID'] + suit['name'] = entry['SuitName'] + suit['mods'] = entry['SuitMods'] + suitloadout_slotid = self.suit_loadout_id_from_loadoutid(entry['LoadoutID']) # Make the new loadout, in the CAPI format new_loadout = {