Merge pull request #1798 from EDCD/fix/1042/centralise-plugin-tracking

Move core plugin 'location' tracking into monitor.py
This commit is contained in:
Athanasius authored and GitHub committed 2023-01-17 11:31:13 +00:00
commit 9f0edc5a29
8 files changed
+667 -506

No files matched your search

+11 -8
View File
@@ -326,10 +326,12 @@ sys.path: {sys.path}'''
raise companion.CmdrError()
elif (
data['lastSystem']['name'] != monitor.system or
((data['commander']['docked'] and data['lastStarport']['name'] or None) != monitor.station) or
data['ship']['id'] != monitor.state['ShipID'] or
data['ship']['name'].lower() != monitor.state['ShipType']
data['lastSystem']['name'] != monitor.state['SystemName']
or (
(data['commander']['docked'] and data['lastStarport']['name'] or None) != monitor.state['StationName']
)
or data['ship']['id'] != monitor.state['ShipID']
or data['ship']['name'].lower() != monitor.state['ShipType']
):
raise companion.ServerLagging()
@@ -431,10 +433,11 @@ sys.path: {sys.path}'''
new_data = capi_response.capi_data
# might have undocked while we were waiting for retry in which case station data is unreliable
if new_data['commander'].get('docked') and \
deep_get(new_data, 'lastSystem', 'name') == monitor.system and \
deep_get(new_data, 'lastStarport', 'name') == monitor.station:
if (
new_data['commander'].get('docked')
and deep_get(new_data, 'lastSystem', 'name') == monitor.state['SystemName']
and deep_get(new_data, 'lastStarport', 'name') == monitor.state['StationName']
):
data = new_data
if args.s:
+38 -26
View File
@@ -1089,7 +1089,7 @@ class AppWindow(object):
self.status['text'] = _('CAPI query aborted: GameVersion unknown')
return
if not monitor.system:
if not monitor.state['SystemName']:
logger.trace_if('capi.worker', 'Aborting Query: Current star system unknown')
# LANG: CAPI queries aborted because current star system name unknown
self.status['text'] = _('CAPI query aborted: Current system unknown')
@@ -1272,30 +1272,32 @@ class AppWindow(object):
f"not {capi_response.capi_data['commander'].get('docked')!r}")
raise companion.ServerLagging()
elif capi_response.capi_data['lastSystem']['name'] != monitor.system:
elif capi_response.capi_data['lastSystem']['name'] != monitor.state['SystemName']:
# CAPI system must match last journal one
logger.warning(f"{capi_response.capi_data['lastSystem']['name']!r} != {monitor.system!r}")
logger.warning(f"{capi_response.capi_data['lastSystem']['name']!r} != "
f"{monitor.state['SystemName']!r}")
raise companion.ServerLagging()
elif capi_response.capi_data['lastStarport']['name'] != monitor.station:
if monitor.state['OnFoot'] and monitor.station:
logger.warning(f"({capi_response.capi_data['lastStarport']['name']!r} != {monitor.station!r}) AND "
f"{monitor.state['OnFoot']!r} and {monitor.station!r}")
elif capi_response.capi_data['lastStarport']['name'] != monitor.state['StationName']:
if monitor.state['OnFoot'] and monitor.state['StationName']:
logger.warning(f"({capi_response.capi_data['lastStarport']['name']!r} != "
f"{monitor.state['StationName']!r}) AND "
f"{monitor.state['OnFoot']!r} and {monitor.state['StationName']!r}")
raise companion.ServerLagging()
elif capi_response.capi_data['commander']['docked'] and monitor.station is None:
elif capi_response.capi_data['commander']['docked'] and monitor.state['StationName'] is None:
# Likely (re-)Embarked on ship docked at an EDO settlement.
# Both Disembark and Embark have `"Onstation": false` in Journal.
# So there's nothing to tell us which settlement we're (still,
# or now, if we came here in Apex and then recalled ship) docked at.
logger.debug("docked AND monitor.station is None - so EDO settlement?")
logger.debug("docked AND monitor.state['StationName'] is None - so EDO settlement?")
raise companion.NoMonitorStation()
self.capi_query_holdoff_time = capi_response.query_time + companion.capi_query_cooldown
elif capi_response.capi_data['lastStarport']['id'] != monitor.station_marketid:
elif capi_response.capi_data['lastStarport']['id'] != monitor.state['MarketID']:
logger.warning(f"MarketID mis-match: {capi_response.capi_data['lastStarport']['id']!r} !="
f" {monitor.station_marketid!r}")
f" {monitor.state['MarketID']!r}")
raise companion.ServerLagging()
elif not monitor.state['OnFoot'] and capi_response.capi_data['ship']['id'] != monitor.state['ShipID']:
@@ -1526,7 +1528,7 @@ class AppWindow(object):
self.update_suit_text()
self.suit_show_if_set()
self.edit_menu.entryconfigure(0, state=monitor.system and tk.NORMAL or tk.DISABLED) # Copy
self.edit_menu.entryconfigure(0, state=monitor.state['SystemName'] and tk.NORMAL or tk.DISABLED) # Copy
if entry['event'] in (
'Undocked',
@@ -1589,8 +1591,8 @@ class AppWindow(object):
err = plug.notify_journal_entry(
monitor.cmdr,
monitor.is_beta,
monitor.system,
monitor.station,
monitor.state['SystemName'],
monitor.state['StationName'],
entry,
monitor.state
)
@@ -1606,7 +1608,7 @@ class AppWindow(object):
# Only if configured to do so
if (not config.get_int('output') & config.OUT_MKT_MANUAL
and config.get_int('output') & config.OUT_STATION_ANY):
if entry['event'] in ('StartUp', 'Location', 'Docked') and monitor.station:
if entry['event'] in ('StartUp', 'Location', 'Docked') and monitor.state['StationName']:
# TODO: Can you log out in a docked Taxi and then back in to
# the taxi, so 'Location' should be covered here too ?
if entry['event'] == 'Docked' and entry.get('Taxi'):
@@ -1728,11 +1730,16 @@ class AppWindow(object):
def system_url(self, system: str) -> str | None:
"""Despatch a system URL to the configured handler."""
return plug.invoke(config.get_str('system_provider'), 'EDSM', 'system_url', monitor.system)
return plug.invoke(
config.get_str('system_provider'), 'EDSM', 'system_url', monitor.state['SystemName']
)
def station_url(self, station: str) -> str | None:
"""Despatch a station URL to the configured handler."""
return plug.invoke(config.get_str('station_provider'), 'eddb', 'station_url', monitor.system, monitor.station)
return plug.invoke(
config.get_str('station_provider'), 'eddb', 'station_url',
monitor.state['SystemName'], monitor.state['StationName']
)
def cooldown(self) -> None:
"""Display and update the cooldown timer for 'Update' button."""
@@ -1746,12 +1753,14 @@ class AppWindow(object):
else:
self.button['text'] = self.theme_button['text'] = _('Update') # LANG: Update button in main window
self.button['state'] = self.theme_button['state'] = (monitor.cmdr and
monitor.mode and
monitor.mode != 'CQC' and
not monitor.state['Captain'] and
monitor.system and
tk.NORMAL or tk.DISABLED)
self.button['state'] = self.theme_button['state'] = (
monitor.cmdr and
monitor.mode and
monitor.mode != 'CQC' and
not monitor.state['Captain'] and
monitor.state['SystemName'] and
tk.NORMAL or tk.DISABLED
)
if sys.platform == 'win32':
def ontop_changed(self, event=None) -> None:
@@ -1761,9 +1770,12 @@ class AppWindow(object):
def copy(self, event=None) -> None:
"""Copy system, and possible station, name to clipboard."""
if monitor.system:
if monitor.state['SystemName']:
self.w.clipboard_clear()
self.w.clipboard_append(monitor.station and f'{monitor.system},{monitor.station}' or monitor.system)
self.w.clipboard_append(
f"{monitor.state['SystemName']},{monitor.state['StationName']}" if monitor.state['StationName']
else monitor.state['SystemName']
)
def help_general(self, event=None) -> None:
"""Open Wiki Help page in browser."""
@@ -1898,7 +1910,7 @@ class AppWindow(object):
defaultextension=default_extension,
filetypes=[('JSON', '.json'), ('All Files', '*')],
initialdir=config.get_str('outdir'),
initialfile=f'{monitor.system}.{monitor.station}.{timestamp}'
initialfile=f"{monitor.state['SystemName']}.{monitor.state['StationName']}.{timestamp}"
)
if not f:
return
+96 -50
View File
@@ -606,55 +606,63 @@ This gets called when EDMarketConnector sees a new entry in the game's journal.
Content of `state` (updated to the current journal entry):
| Field | Type | Description |
| :------------------- | :-------------------------: |:----------------------------------------------------------------------------------------------------------------|
| `GameLanguage` | `Optional[str]` | `language` value from `Fileheader` event. |
| `GameVersion` | `Optional[str]` | `version` value from `Fileheader` event. |
| `GameBuild` | `Optional[str]` | `build` value from `Fileheader` event. |
| `Captain` | `Optional[str]` | Name of the commander who's crew you're on, if any |
| `Cargo` | `dict` | Current cargo. Note that this will be totals, and any mission specific duplicates will be counted together |
| `CargoJSON` | `dict` | content of cargo.json as of last read. |
| `Credits` | `int` | Current credits balance |
| `FID` | `str` | Frontier commander ID |
| `Horizons` | `bool` | From `LoadGame` event. |
| `Odyssey` | `bool` | From `LoadGame` event. `False` if not present, else the event value. |
| `Loan` | `Optional[int]` | Current loan amount, if any |
| `Raw` | `dict` | Current raw engineering materials |
| `Manufactured` | `dict` | Current manufactured engineering materials |
| `Encoded` | `dict` | Current encoded engineering materials |
| `Component` | `dict` | Current component materials |
| `Engineers` | `dict` | Current Raw engineering materials |
| `Rank` | `Dict[str, Tuple[int, int]` | Current ranks, each entry is a tuple of the current rank, and age |
| `Statistics` | `dict` | Contents of a Journal Statistics event, ie, data shown in the stats panel. See the Journal manual for more info |
| `Role` | `Optional[str]` | Current role if in multi-crew, one of `Idle`, `FireCon`, `FighterCon` |
| `Friends` | `set` | Currently online friend |
| `ShipID` | `int` | Frontier ID of current ship |
| `ShipIdent` | `str` | Current user-set ship ID |
| `ShipName` | `str` | Current user-set ship name |
| `ShipType` | `str` | Internal name for the current ship type |
| `HullValue` | `int` | Current ship value, excluding modules |
| `ModulesValue` | `int` | Value of the current ship's modules |
| `Rebuy` | `int` | Current ship's rebuy cost |
| `Modules` | `dict` | Currently fitted modules |
| `NavRoute` | `dict` | Last plotted multi-hop route[1] |
| `ModuleInfo` | `dict` | Last loaded ModulesInfo.json data |
| `IsDocked` | `bool` | Whether the Cmdr is currently docked *in their own ship*. |
| `OnFoot` | `bool` | Whether the Cmdr is on foot |
| `Component` | `dict` | 'Component' MicroResources in Odyssey, `int` count each. |
| `Item` | `dict` | 'Item' MicroResources in Odyssey, `int` count each. |
| `Consumable` | `dict` | 'Consumable' MicroResources in Odyssey, `int` count each. |
| `Data` | `dict` | 'Data' MicroResources in Odyssey, `int` count each. |
| `BackPack` | `dict` | `dict` of Odyssey MicroResources in backpack. |
| `BackpackJSON` | `dict` | Content of Backpack.json as of last read. |
| `ShipLockerJSON` | `dict` | Content of ShipLocker.json as of last read. |
| `SuitCurrent` | `dict` | CAPI-returned data of currently worn suit. NB: May be `None` if no data. |
| `Suits` | `dict`[2] | CAPI-returned data of owned suits. NB: May be `None` if no data. |
| `SuitLoadoutCurrent` | `dict` | CAPI-returned data of current Suit Loadout. NB: May be `None` if no data. |
| `SuitLoadouts` | `dict`[2] | CAPI-returned data of all Suit Loadouts. NB: May be `None` if no data. |
| `Taxi` | `Optional[bool]` | Whether or not we're currently in a taxi. NB: This is best effort with what the journals provide. |
| `Dropship` | `Optional[bool]` | Whether or not the above taxi is a Dropship |
| `Body` | `Optional[str]` | The body we're currently on / in the SOI of |
| `BodyType` | `Optional[str]` | The type of body that `Body` refers to |
| Field | Type | Description |
|:----------------------|:---------------------------:|:----------------------------------------------------------------------------------------------------------------|
| `GameLanguage` | `Optional[str]` | `language` value from `Fileheader` event. |
| `GameVersion` | `Optional[str]` | `version` value from `Fileheader` event. |
| `GameBuild` | `Optional[str]` | `build` value from `Fileheader` event. |
| `Captain`[3] | `Optional[str]` | Name of the commander who's crew you're on, if any |
| `Cargo` | `dict` | Current cargo. Note that this will be totals, and any mission specific duplicates will be counted together |
| `CargoJSON` | `dict` | content of cargo.json as of last read. |
| `Credits` | `int` | Current credits balance |
| `FID` | `str` | Frontier commander ID |
| `Horizons` | `bool` | From `LoadGame` event. |
| `Odyssey` | `bool` | From `LoadGame` event. `False` if not present, else the event value. |
| `Loan` | `Optional[int]` | Current loan amount, if any |
| `Raw` | `dict` | Current raw engineering materials |
| `Manufactured` | `dict` | Current manufactured engineering materials |
| `Encoded` | `dict` | Current encoded engineering materials |
| `Component` | `dict` | Current component materials |
| `Engineers` | `dict` | Current Raw engineering materials |
| `Rank` | `Dict[str, Tuple[int, int]` | Current ranks, each entry is a tuple of the current rank, and age |
| `Statistics` | `dict` | Contents of a Journal Statistics event, ie, data shown in the stats panel. See the Journal manual for more info |
| `Role` | `Optional[str]` | Current role if in multi-crew, one of `Idle`, `FireCon`, `FighterCon` |
| `Friends` | `set` | Currently online friend |
| `ShipID` | `int` | Frontier ID of current ship |
| `ShipIdent` | `str` | Current user-set ship ID |
| `ShipName` | `str` | Current user-set ship name |
| `ShipType` | `str` | Internal name for the current ship type |
| `HullValue` | `int` | Current ship value, excluding modules |
| `ModulesValue` | `int` | Value of the current ship's modules |
| `Rebuy` | `int` | Current ship's rebuy cost |
| `Modules` | `dict` | Currently fitted modules |
| `NavRoute` | `dict` | Last plotted multi-hop route[1] |
| `ModuleInfo` | `dict` | Last loaded ModulesInfo.json data |
| `IsDocked` | `bool` | Whether the Cmdr is currently docked *in their own ship*. |
| `OnFoot`[3] | `bool` | Whether the Cmdr is on foot |
| `Component` | `dict` | 'Component' MicroResources in Odyssey, `int` count each. |
| `Item` | `dict` | 'Item' MicroResources in Odyssey, `int` count each. |
| `Consumable` | `dict` | 'Consumable' MicroResources in Odyssey, `int` count each. |
| `Data` | `dict` | 'Data' MicroResources in Odyssey, `int` count each. |
| `BackPack` | `dict` | `dict` of Odyssey MicroResources in backpack. |
| `BackpackJSON` | `dict` | Content of Backpack.json as of last read. |
| `ShipLockerJSON` | `dict` | Content of ShipLocker.json as of last read. |
| `SuitCurrent` | `dict` | CAPI-returned data of currently worn suit. NB: May be `None` if no data. |
| `Suits` | `dict`[2] | CAPI-returned data of owned suits. NB: May be `None` if no data. |
| `SuitLoadoutCurrent` | `dict` | CAPI-returned data of current Suit Loadout. NB: May be `None` if no data. |
| `SuitLoadouts` | `dict`[2] | CAPI-returned data of all Suit Loadouts. NB: May be `None` if no data. |
| `Taxi` | `Optional[bool]` | Whether or not we're currently in a taxi. NB: This is best effort with what the journals provide. |
| `Dropship` | `Optional[bool]` | Whether or not the above taxi is a Dropship |
| `SystemAddress`[3] | `Optional[int]` | Unique [ID64](http://disc.thargoid.space/ID64) of the star system we're currently in |
| `SystemName`[3] | `Optional[str]` | Name of the star system we're currently in |
| `SystemPopulation`[3] | `Optional[int]` | Population of the star system we're currently in |
| `StarPos`[3] | `Optional[tuple[float]]` | Galaxy co-ordinates of the system we're currently in |
| `Body`[3][4] | `Optional[str]` | Name of the body we're currently on / in the SOI of |
| `BodyID`[3][4] | `Optional[int]` | ID of the body we're currently on / in the SOI of |
| `BodyType`[3][4] | `Optional[str]` | The type of body that `Body` refers to |
| `StationName`[3] | `Optional[str]` | Name of the station we're docked at, if applicable |
| `MarketID`[3] | `Optional[str]` | MarketID of the station we're docked at, if applicable |
| `StationType`[3] | `Optional[str]` | Type of the station we're docked at, if applicable |
[1] - Contents of `NavRoute` not changed if a `NavRouteClear` event is seen,
but plugins will see the `NavRouteClear` event.
@@ -676,6 +684,31 @@ least one member is missing, so the indices are not contiguous). We choose to
always convert to the integer-keyed `dict` form so that code utilising the data
is simpler.
[3] - Forced to `None` if the player joins another player's ship in remote
multi-crew.
[4] - There are some caveats with the Body data. Firstly the name and ID
can be for the orbital station or fleet carrier the player is docked at.
Check 'BodyType' before using the values.
Secondly there is an issue with close-orbiting binary bodies. If the player:
1. Enters Orbital Cruise around a Body an 'ApproachBody' event is emitted
and the tracking will update to reflect this.
2. If the player then flies *in Orbital Cruise without entering Supercruise
proper* to the close-orbiting binary partner of the Body then *there is no
new 'ApproachBody' event to indicate the new Body's details*. **Thus this
tracking will incorrectly indicate the first Body still**.
So, before making use of any of this Body state a plugin should:
1. Have a `dashboard_entry()` method and track the Body name present in its
data.
2. Cross-check that Body name with `state['Body']` before making use of any
of `state'`s Body data.
See `plugins/eddn.py` for an example of this in `export_journal_codexentry()`.
New in version 4.1.6:
`CargoJSON` contains the raw data from the last read of `Cargo.json` passed
@@ -765,13 +798,26 @@ re-start EDMarketConnector. That will be present when plugins are invoked
with the synthetic `StartUp` event. NB: Might just be a `NavRouteClear` event
if that's what was in the file.
New in version 5.8.0:
`StarPos`, `SystemAddress`, `SystemName` and `SystemPopulation` have been
added to the `state` dictionary. Best efforts data pertaining to the star
system the player is in.
`BodyID` and `BodyType` have been added to the `state` dictionary. These
now track in the same manner as prior core EDDN plugin code. Check the
documentation above for some caveats. Do not just blindly use this data, or
the 'Body' name value.
`StationName`, `MarketID`, and `StationType` added to the `state` dictionary.
___
##### Synthetic Events
A special "StartUp" entry is sent if EDMarketConnector is started while the
game is already running. In this case you won't receive initial events such as
"LoadGame", "Rank", "Location", etc. However the `state` dictionary will
"LoadGame", "Rank", "Location", etc. However, the `state` dictionary will
reflect the cumulative effect of these missed events.
**NB: Any of the values in this might be `None` if the Cmdr has loaded into
+305 -186
View File
@@ -14,9 +14,7 @@ from collections import OrderedDict, defaultdict
from os import SEEK_END, SEEK_SET, listdir
from os.path import basename, expanduser, getctime, isdir, join
from time import gmtime, localtime, mktime, sleep, strftime, strptime, time
from typing import TYPE_CHECKING, Any, BinaryIO, Dict, List, MutableMapping, Optional
from typing import OrderedDict as OrderedDictT
from typing import Tuple
from typing import TYPE_CHECKING, Any, BinaryIO, MutableMapping, Tuple
if TYPE_CHECKING:
import tkinter
@@ -91,11 +89,11 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
# TODO(A_D): A bunch of these should be switched to default values (eg '' for strings) and no longer be Optional
FileSystemEventHandler.__init__(self) # futureproofing - not need for current version of watchdog
self.root: 'tkinter.Tk' = None # type: ignore # Don't use Optional[] - mypy thinks no methods
self.currentdir: Optional[str] = None # The actual logdir that we're monitoring
self.logfile: Optional[str] = None
self.observer: Optional['Observer'] = None
self.currentdir: str | None = None # The actual logdir that we're monitoring
self.logfile: str | None = None
self.observer: 'Observer' | None = None
self.observed = None # a watchdog ObservedWatch, or None if polling
self.thread: Optional[threading.Thread] = None
self.thread: threading.Thread | None = None
# For communicating journal entries back to main thread
self.event_queue: queue.Queue = queue.Queue(maxsize=0)
@@ -112,27 +110,19 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
self.game_was_running = False # For generation of the "ShutDown" event
# Context for journal handling
self.version: Optional[str] = None
self.version_semantic: Optional[semantic_version.Version] = None
self.version: str | None = None
self.version_semantic: semantic_version.Version | None = None
self.is_beta = False
self.mode: Optional[str] = None
self.group: Optional[str] = None
self.cmdr: Optional[str] = None
self.planet: Optional[str] = None
self.system: Optional[str] = None
self.station: Optional[str] = None
self.station_marketid: Optional[int] = None
self.stationtype: Optional[str] = None
self.coordinates: Optional[Tuple[float, float, float]] = None
self.systemaddress: Optional[int] = None
self.systempopulation: Optional[int] = None
self.started: Optional[int] = None # Timestamp of the LoadGame event
self.mode: str | None = None
self.group: str | None = None
self.cmdr: str | None = None
self.started: int | None = None # Timestamp of the LoadGame event
self._navroute_retries_remaining = 0
self._last_navroute_journal_timestamp: Optional[float] = None
self._last_navroute_journal_timestamp: float | None = None
self._fcmaterials_retries_remaining = 0
self._last_fcmaterials_journal_timestamp: Optional[float] = None
self._last_fcmaterials_journal_timestamp: float | None = None
# For determining Live versus Legacy galaxy.
# The assumption is gameversion will parse via `coerce()` and always
@@ -144,7 +134,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
def __init_state(self) -> None:
# Cmdr state shared with EDSM and plugins
# If you change anything here update PLUGINS.md documentation!
self.state: Dict = {
self.state: dict = {
'GameLanguage': None, # From `Fileheader
'GameVersion': None, # From `Fileheader
'GameBuild': None, # From `Fileheader
@@ -195,8 +185,13 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
'Taxi': None, # True whenever we are _in_ a taxi. ie, this is reset on Disembark etc.
'Dropship': None, # Best effort as to whether or not the above taxi is a dropship.
'StarPos': None, # Best effort current system's galaxy position.
'SystemAddress': None,
'SystemName': None,
'SystemPopulation': None,
'Body': None,
'BodyID': None,
'BodyType': None,
'StationName': None,
'NavRoute': None,
}
@@ -274,7 +269,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
logger.debug('Done.')
return True
def journal_newest_filename(self, journals_dir) -> Optional[str]:
def journal_newest_filename(self, journals_dir) -> str | None:
"""
Determine the newest Journal file name.
@@ -306,19 +301,20 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
self.mode = None
self.group = None
self.cmdr = None
self.planet = None
self.system = None
self.station = None
self.station_marketid = None
self.stationtype = None
self.state['SystemAddress'] = None
self.state['SystemName'] = None
self.state['SystemPopulation'] = None
self.state['StarPos'] = None
self.state['Body'] = None
self.state['BodyID'] = None
self.state['BodyType'] = None
self.state['StationName'] = None
self.state['MarketID'] = None
self.state['StationType'] = None
self.stationservices = None
self.coordinates = None
self.systemaddress = None
self.is_beta = False
self.state['OnFoot'] = False
self.state['IsDocked'] = False
self.state['Body'] = None
self.state['BodyType'] = None
if self.observed:
logger.debug('self.observed: Calling unschedule_all()')
@@ -417,24 +413,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
if self.game_was_running:
logger.info("Game is/was running, so synthesizing StartUp event for plugins")
# Game is running locally
entry: OrderedDictT[str, Any] = OrderedDict([
('timestamp', strftime('%Y-%m-%dT%H:%M:%SZ', gmtime())),
('event', 'StartUp'),
('StarSystem', self.system),
('StarPos', self.coordinates),
('SystemAddress', self.systemaddress),
('Population', self.systempopulation),
])
if self.planet:
entry['Body'] = self.planet
entry['Docked'] = bool(self.station)
if self.station:
entry['StationName'] = self.station
entry['StationType'] = self.stationtype
entry['MarketID'] = self.station_marketid
entry = self.synthesize_startup_event()
self.event_queue.put(json.dumps(entry, separators=(', ', ':')))
@@ -456,7 +435,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
# Check whether new log file started, e.g. client (re)started.
if emitter and emitter.is_alive():
new_journal_file: Optional[str] = self.logfile # updated by on_created watchdog callback
new_journal_file: str | None = self.logfile # updated by on_created watchdog callback
else:
# Poll
@@ -535,6 +514,41 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
logger.debug('Done.')
def synthesize_startup_event(self) -> dict[str, Any]:
"""
Synthesize a 'StartUp' event to notify plugins of initial state.
May be called, e.g. after 'catch up' loading of current latest
journal file on startup, or when a new journal file is detected without
the game running locally.
:return: Synthesized event as a dict
"""
entry: dict[str, Any] = {
'timestamp': strftime('%Y-%m-%dT%H:%M:%SZ', gmtime()),
'event': 'StartUp',
'StarSystem': self.state['SystemName'],
'StarPos': self.state['StarPos'],
'SystemAddress': self.state['SystemAddress'],
'Population': self.state['SystemPopulation'],
}
if self.state['Body']:
entry['Body'] = self.state['Body']
entry['BodyID'] = self.state['BodyID']
entry['BodyType'] = self.state['BodyType']
if self.state['StationName']:
entry['Docked'] = True
entry['MarketID'] = self.state['MarketID']
entry['StationName'] = self.state['StationName']
entry['StationType'] = self.state['StationType']
else:
entry['Docked'] = False
return entry
def parse_entry(self, line: bytes) -> MutableMapping[str, Any]: # noqa: C901, CCR001
"""
Parse a Journal JSON line.
@@ -564,14 +578,16 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
self.cmdr = None
self.mode = None
self.group = None
self.planet = None
self.system = None
self.station = None
self.station_marketid = None
self.stationtype = None
self.state['SystemAddress'] = None
self.state['SystemName'] = None
self.state['SystemPopulation'] = None
self.state['StarPos'] = None
self.state['Body'] = None
self.state['BodyID'] = None
self.state['StationName'] = None
self.state['MarketID'] = None
self.state['StationType'] = None
self.stationservices = None
self.coordinates = None
self.systemaddress = None
self.started = None
self.__init_state()
@@ -600,34 +616,35 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
self.mode = entry.get('GameMode')
self.group = entry.get('Group')
self.planet = None
self.system = None
self.station = None
self.station_marketid = None
self.stationtype = None
self.state['SystemAddress'] = None
self.state['SystemName'] = None
self.state['SystemPopulation'] = None
self.state['StarPos'] = None
self.state['Body'] = None
self.state['BodyID'] = None
self.state['BodyType'] = None
self.state['StationName'] = None
self.state['MarketID'] = None
self.state['StationType'] = None
self.stationservices = None
self.coordinates = None
self.systemaddress = None
self.started = timegm(strptime(entry['timestamp'], '%Y-%m-%dT%H:%M:%SZ'))
# Don't set Ship, ShipID etc since this will reflect Fighter or SRV if starting in those
self.state.update({
'Captain': None,
'Credits': entry['Credits'],
'FID': entry.get('FID'), # From 3.3
'Horizons': entry['Horizons'], # From 3.0
'Odyssey': entry.get('Odyssey', False), # From 4.0 Odyssey
'Loan': entry['Loan'],
'Captain': None,
'Credits': entry['Credits'],
'FID': entry.get('FID'), # From 3.3
'Horizons': entry['Horizons'], # From 3.0
'Odyssey': entry.get('Odyssey', False), # From 4.0 Odyssey
'Loan': entry['Loan'],
# For Odyssey, by 4.0.0.100, and at least from Horizons 3.8.0.201 the order of events changed
# to LoadGame being after some 'status' events.
# 'Engineers': {}, # 'EngineerProgress' event now before 'LoadGame'
# 'Rank': {}, # 'Rank'/'Progress' events now before 'LoadGame'
# 'Reputation': {}, # 'Reputation' event now before 'LoadGame'
'Statistics': {}, # Still after 'LoadGame' in 4.0.0.903
'Role': None,
'Taxi': None,
'Dropship': None,
'Body': None,
'BodyType': None,
# 'Engineers': {}, # 'EngineerProgress' event now before 'LoadGame'
# 'Rank': {}, # 'Rank'/'Progress' events now before 'LoadGame'
# 'Reputation': {}, # 'Reputation' event now before 'LoadGame'
'Statistics': {}, # Still after 'LoadGame' in 4.0.0.903
'Role': None,
'Taxi': None,
'Dropship': None,
})
if entry.get('Ship') is not None and self._RE_SHIP_ONFOOT.search(entry['Ship']):
self.state['OnFoot'] = True
@@ -739,9 +756,9 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
modules.pop(from_slot, None)
elif event_type == 'undocked':
self.station = None
self.station_marketid = None
self.stationtype = None
self.state['StationName'] = None
self.state['MarketID'] = None
self.state['StationType'] = None
self.stationservices = None
self.state['IsDocked'] = False
@@ -761,9 +778,11 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
# • StationName (if at a station)
# • StationType
# • MarketID
self.station = None
self.state['StationName'] = None
self.state['MarketID'] = None
if entry.get('OnStation'):
self.station = entry.get('StationName', '')
self.state['StationName'] = entry.get('StationName', '')
self.state['MarketID'] = entry.get('MarketID', '')
self.state['OnFoot'] = False
self.state['Taxi'] = entry['Taxi']
@@ -791,10 +810,10 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
# • MarketID
if entry.get('OnStation', False):
self.station = entry.get('StationName', '')
self.state['StationName'] = entry.get('StationName', '')
else:
self.station = None
self.state['StationName'] = None
self.state['OnFoot'] = True
if self.state['Taxi'] is not None and self.state['Taxi'] != entry.get('Taxi', False):
@@ -809,77 +828,204 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
self.state['Taxi'] = False
self.state['Dropship'] = False
elif event_type == 'supercruiseexit':
# For any orbital station we have no way of determining the body
# it orbits:
#
# In-ship Status.json doesn't specify this.
# On-foot Status.json lists the station itself as Body.
# Location for stations (on-foot or in-ship) has station as Body.
# SupercruiseExit (own ship or taxi) lists the station as the Body.
if entry['BodyType'] == 'Station':
self.state['Body'] = None
self.state['BodyID'] = None
elif event_type == 'docked':
###############################################################
# Track: Station
###############################################################
self.state['IsDocked'] = True
self.station = entry.get('StationName') # May be None
self.station_marketid = entry.get('MarketID') # May be None
self.stationtype = entry.get('StationType') # May be None
self.state['StationName'] = entry.get('StationName') # It may be None
self.state['MarketID'] = entry.get('MarketID') # It may be None
self.state['StationType'] = entry.get('StationType') # It may be None
self.stationservices = entry.get('StationServices') # None under E:D < 2.4
# No need to set self.state['Taxi'] or Dropship here, if its those, the next event is a Disembark anyway
# No need to set self.state['Taxi'] or Dropship here, if it's
# those, the next event is a Disembark anyway
###############################################################
elif event_type in ('location', 'fsdjump', 'carrierjump'):
# alpha4 - any changes ?
# Location:
# New in Odyssey:
# • Taxi: bool
# • Multicrew: bool
# • InSRV: bool
# • OnFoot: bool
"""
Notes on tracking of a player's location.
Body
---
There are some caveats about tracking Body name, ID and type,
mostly due to close-orbiting binary planets/moons.
Presence on or near a Body is indicated in several scenarios:
1. When the player logs in.
2. When the player's location changes due to being docked
on a Fleet Carrier when it jumps.
3. When the player flies within Orbital Cruise range of a
Body.
For the first case this will always be a 'Location' event.
If landed on a Body, or docked at a surface port then this
will be indicated. However, if docked at an orbital station
the 'Body' is the name of that station, with 'BodyType' having
'Station' as its value.
In the second case although it *should* be a 'CarrierJump'
event, for a while now it's actually been a 'Location' event.
This should follow the same rules as being docked at an
orbital station.
For the last case there are some caveats to do with close
orbiting binary bodies:
1. 'ApproachBody' indicates presence near the Body in question.
2. 'LeaveBody' indicates the player is no longer considered
to be near the Body. This is specifically when no longer
in Orbital Cruise around the Body such that the HUD for that
has been switched out for the normal SuperCruise one.
3. 'SupercruiseExit' does not indicate any change of presence
near a Body.
4. 'SupercruiseEntry' *also* **DOES NOT** indicate that the
player is no longer near the Body. They can easily utilise
Orbital Cruise to rapidly travel around the Body and then
land on it again **without a fresh 'ApproachBody'** event.
The only way to check for this is to utilise the Body (name)
present in `Status.json` data, as this *will* correctly
reflect the second Body.
"""
###############################################################
# Track: Body
###############################################################
if event_type in ('location', 'carrierjump'):
self.planet = entry.get('Body') if entry.get('BodyType') == 'Planet' else None
# We're not guaranteeing this is a planet, rather than a
# station.
self.state['Body'] = entry.get('Body')
self.state['BodyID'] = entry.get('BodyID')
self.state['BodyType'] = entry.get('BodyType')
if event_type == 'location':
logger.trace_if('journal.locations', '"Location" event')
if entry.get('Docked'):
self.state['IsDocked'] = True
elif event_type == 'fsdjump':
self.planet = None
self.state['Body'] = None
self.state['BodyID'] = None
self.state['BodyType'] = None
###############################################################
###############################################################
# Track: IsDocked
###############################################################
if event_type == 'location':
logger.trace_if('journal.locations', '"Location" event')
self.state['IsDocked'] = entry.get('Docked', False)
###############################################################
###############################################################
# Track: Current System
###############################################################
if 'StarPos' in entry:
# Plugins need this as well, so copy in state
self.state['StarPos'] = self.coordinates = tuple(entry['StarPos']) # type: ignore
self.systemaddress = entry.get('SystemAddress')
self.systempopulation = entry.get('Population')
if entry['StarSystem'] == 'ProvingGround':
self.system = 'CQC'
self.state['StarPos'] = tuple(entry['StarPos']) # type: ignore
else:
self.system = entry['StarSystem']
logger.warning(f"'{event_type}' event without 'StarPos' !!!:\n{entry}\n")
self.station = entry.get('StationName') # May be None
# If on foot in-station 'Docked' is false, but we have a
# 'BodyType' of 'Station', and the 'Body' is the station name
# NB: No MarketID
if entry.get('BodyType') and entry['BodyType'] == 'Station':
self.station = entry.get('Body')
if 'SystemAddress' not in entry:
logger.warning(f"{event_type} event without SystemAddress !!!:\n{entry}\n")
self.station_marketid = entry.get('MarketID') # May be None
self.stationtype = entry.get('StationType') # May be None
self.stationservices = entry.get('StationServices') # None in Odyssey for on-foot 'Location'
# But we'll still *use* the value, because if a 'location' event doesn't
# have this we've still moved and now don't know where and MUST NOT
# continue to use any old value.
# Yes, explicitly state `None` here, so it's crystal clear.
self.state['SystemAddress'] = entry.get('SystemAddress', None)
self.state['SystemPopulation'] = entry.get('Population')
if entry['StarSystem'] == 'ProvingGround':
self.state['SystemName'] = 'CQC'
else:
self.state['SystemName'] = entry['StarSystem']
###############################################################
###############################################################
# Track: Current station, if applicable
###############################################################
if event_type == 'fsdjump':
self.state['StationName'] = None
self.state['MarketID'] = None
self.state['StationType'] = None
self.stationservices = None
else:
self.state['StationName'] = entry.get('StationName') # It may be None
# If on foot in-station 'Docked' is false, but we have a
# 'BodyType' of 'Station', and the 'Body' is the station name
# NB: No MarketID
if entry.get('BodyType') and entry['BodyType'] == 'Station':
self.state['StationName'] = entry.get('Body')
self.state['MarketID'] = entry.get('MarketID') # May be None
self.state['StationType'] = entry.get('StationType') # May be None
self.stationservices = entry.get('StationServices') # None in Odyssey for on-foot 'Location'
###############################################################
###############################################################
# Track: Whether in a Taxi/Dropship
###############################################################
self.state['Taxi'] = entry.get('Taxi', None)
if not self.state['Taxi']:
self.state['Dropship'] = None
###############################################################
elif event_type == 'approachbody':
self.planet = entry['Body']
self.state['Body'] = entry['Body']
self.state['BodyType'] = 'Planet' # Best guess. Journal says always planet.
self.state['BodyID'] = entry.get('BodyID')
# This isn't in the event, but Journal doc for ApproachBody says:
# when in Supercruise, and distance from planet drops to within the 'Orbital Cruise' zone
# Used in plugins/eddn.py for setting entry Body/BodyType
# on 'docked' events when Planetary.
self.state['BodyType'] = 'Planet'
elif event_type in ('leavebody', 'supercruiseentry'):
self.planet = None
elif event_type == 'leavebody':
# Triggered when ship goes above Orbital Cruise altitude, such
# that a new 'ApproachBody' would get triggered if the ship
# went back down.
self.state['Body'] = None
self.state['BodyID'] = None
self.state['BodyType'] = None
elif event_type == 'supercruiseentry':
# We only clear Body state if the Type is Station. This is
# because we won't get a fresh ApproachBody if we don't leave
# Orbital Cruise but land again.
if self.state['BodyType'] == 'Station':
self.state['Body'] = None
self.state['BodyID'] = None
self.state['BodyType'] = None
###############################################################
# Track: Current station, if applicable
###############################################################
self.state['StationName'] = None
self.state['MarketID'] = None
self.state['StationType'] = None
self.stationservices = None
###############################################################
elif event_type == 'music':
if entry['MusicTrack'] == 'MainMenu':
# We'll get new Body state when the player logs back into
# the game.
self.state['Body'] = None
self.state['BodyID'] = None
self.state['BodyType'] = None
elif event_type in ('rank', 'promotion'):
payload = dict(entry)
payload.pop('event')
@@ -1563,18 +1709,19 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
elif event_type == 'joinacrew':
self.state['Captain'] = entry['Captain']
self.state['Role'] = 'Idle'
self.planet = None
self.system = None
self.station = None
self.station_marketid = None
self.stationtype = None
self.stationservices = None
self.coordinates = None
self.systemaddress = None
self.state['OnFoot'] = False
self.state['StarPos'] = None
self.state['SystemName'] = None
self.state['SystemAddress'] = None
self.state['SystemPopulation'] = None
self.state['StarPos'] = None
self.state['Body'] = None
self.state['BodyID'] = None
self.state['BodyType'] = None
self.state['StationName'] = None
self.state['MarketID'] = None
self.state['StationType'] = None
self.stationservices = None
self.state['OnFoot'] = False
elif event_type == 'changecrewrole':
self.state['Role'] = entry['Role']
@@ -1582,17 +1729,18 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
elif event_type == 'quitacrew':
self.state['Captain'] = None
self.state['Role'] = None
self.planet = None
self.system = None
self.station = None
self.station_marketid = None
self.stationtype = None
self.stationservices = None
self.coordinates = None
self.systemaddress = None
self.state['SystemName'] = None
self.state['SystemAddress'] = None
self.state['SystemPopulation'] = None
self.state['StarPos'] = None
self.state['Body'] = None
self.state['BodyID'] = None
self.state['BodyType'] = None
self.state['StationName'] = None
self.state['MarketID'] = None
self.state['StationType'] = None
self.stationservices = None
# TODO: on_foot: Will we get an event after this to know ?
elif event_type == 'friends':
@@ -1677,11 +1825,6 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
# There should be a `Backpack` event as you 'come to' in the
# new location, so no need to zero out BackPack here.
# HACK (not game related / 2021-06-2): self.planet is moved into a more general self.state['Body'].
# This exists to help plugins doing what they SHOULDN'T BE cope. It will be removed at some point.
if self.state['Body'] is None or self.state['BodyType'] == 'Planet':
self.planet = self.state['Body']
return entry
except Exception as ex:
@@ -1919,7 +2062,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
slotid = journal_loadoutid - 4293000000
return slotid
def canonicalise(self, item: Optional[str]) -> str:
def canonicalise(self, item: str | None) -> str:
"""
Produce canonical name for a ship module.
@@ -1956,7 +2099,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
return item.capitalize()
def get_entry(self) -> Optional[MutableMapping[str, Any]]:
def get_entry(self) -> MutableMapping[str, Any] | None:
"""
Pull the next Journal event from the event_queue.
@@ -1980,31 +2123,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
if not self.live and entry['event'] not in (None, 'Fileheader'):
# Game not running locally, but Journal has been updated
self.live = True
if self.station:
entry = OrderedDict([
('timestamp', strftime('%Y-%m-%dT%H:%M:%SZ', gmtime())),
('event', 'StartUp'),
('Docked', True),
('MarketID', self.station_marketid),
('StationName', self.station),
('StationType', self.stationtype),
('StarSystem', self.system),
('StarPos', self.coordinates),
('SystemAddress', self.systemaddress),
])
else:
entry = OrderedDict([
('timestamp', strftime('%Y-%m-%dT%H:%M:%SZ', gmtime())),
('event', 'StartUp'),
('Docked', False),
('StarSystem', self.system),
('StarPos', self.coordinates),
('SystemAddress', self.systemaddress),
])
if entry['event'] == 'Location':
logger.trace_if('journal.locations', 'Appending "Location" event to event_queue')
entry = self.synthesize_startup_event()
self.event_queue.put(json.dumps(entry, separators=(', ', ':')))
@@ -2052,7 +2171,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
return False
def ship(self, timestamped=True) -> Optional[MutableMapping[str, Any]]:
def ship(self, timestamped=True) -> MutableMapping[str, Any] | None:
"""
Produce a subset of data for the current ship.
@@ -2189,7 +2308,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
except OSError:
logger.exception("OSError writing ship loadout to new filename with utf-8 encoding, aborting.")
def coalesce_cargo(self, raw_cargo: List[MutableMapping[str, Any]]) -> List[MutableMapping[str, Any]]:
def coalesce_cargo(self, raw_cargo: list[MutableMapping[str, Any]]) -> list[MutableMapping[str, Any]]:
"""
Coalesce multiple entries of the same cargo into one.
@@ -2210,7 +2329,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
:return: Coalesced data
"""
# self.state['Cargo'].update({self.canonicalise(x['Name']): x['Count'] for x in entry['Inventory']})
out: List[MutableMapping[str, Any]] = []
out: list[MutableMapping[str, Any]] = []
for inventory_item in raw_cargo:
if not any(self.canonicalise(x['Name']) == self.canonicalise(inventory_item['Name']) for x in out):
out.append(dict(inventory_item))
@@ -2251,7 +2370,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
return slots
def _parse_navroute_file(self) -> Optional[dict[str, Any]]:
def _parse_navroute_file(self) -> dict[str, Any] | None:
"""Read and parse NavRoute.json."""
if self.currentdir is None:
raise ValueError('currentdir unset')
@@ -2277,7 +2396,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
return data
def _parse_fcmaterials_file(self) -> Optional[dict[str, Any]]:
def _parse_fcmaterials_file(self) -> dict[str, Any] | None:
"""Read and parse FCMaterials.json."""
if self.currentdir is None:
raise ValueError('currentdir unset')
@@ -2349,7 +2468,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below
self._last_navroute_journal_timestamp = None
return True
def __fcmaterials_retry(self) -> Optional[Dict[str, Any]]:
def __fcmaterials_retry(self) -> dict[str, Any] | None:
"""Retry reading FCMaterials files."""
if self._fcmaterials_retries_remaining == 0:
return None
+31 -55
View File
@@ -42,7 +42,7 @@
# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $#
# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $# ! $#
import tkinter
from typing import TYPE_CHECKING, Any, Mapping, Optional
from typing import TYPE_CHECKING, Any, Mapping
import requests
@@ -69,12 +69,12 @@ class This:
def __init__(self) -> None:
# Main window clicks
self.system_link: tkinter.Widget
self.system: Optional[str] = None
self.system_address: Optional[str] = None
self.system_population: Optional[int] = None
self.system_name: str | None = None
self.system_address: str | None = None
self.system_population: int | None = None
self.station_link: tkinter.Widget
self.station: Optional[str] = None
self.station_marketid: Optional[int] = None
self.station_name: str | None = None
self.station_marketid: int | None = None
self.on_foot = False
@@ -133,9 +133,9 @@ def plugin_app(parent: 'Tk'):
"""
# system label in main window
this.system_link = parent.nametowidget(f".{appname.lower()}.system")
this.system = None
this.system_name = None
this.system_address = None
this.station = None
this.station_name = None
this.station_marketid = None # Frontier MarketID
# station label in main window
this.station_link = parent.nametowidget(f".{appname.lower()}.station")
@@ -154,7 +154,7 @@ def prefs_changed(cmdr: str, is_beta: bool) -> None:
pass
def journal_entry( # noqa: CCR001
def journal_entry(
cmdr: str, is_beta: bool, system: str, station: str,
entry: dict[str, Any],
state: Mapping[str, Any]
@@ -184,59 +184,35 @@ def journal_entry( # noqa: CCR001
return
this.on_foot = state['OnFoot']
# Always update our system address even if we're not currently the provider for system or station, but dont update
# on events that contain "future" data, such as FSDTarget
if entry['event'] in ('Location', 'Docked', 'CarrierJump', 'FSDJump'):
this.system_address = entry.get('SystemAddress') or this.system_address
this.system = entry.get('StarSystem') or this.system
this.system_address = state['SystemAddress']
this.system_name = state['SystemName']
this.system_population = state['SystemPopulation']
this.station_name = state['StationName']
this.station_marketid = state['MarketID']
# We need pop == 0 to set the value so as to clear 'x' in systems with
# no stations.
pop = entry.get('Population')
if pop is not None:
this.system_population = pop
this.station = entry.get('StationName') or this.station
# on_foot station detection
if entry['event'] == 'Location' and entry['BodyType'] == 'Station':
this.station = entry['Body']
this.station_marketid = entry.get('MarketID') or this.station_marketid
# We might pick up StationName in DockingRequested, make sure we clear it if leaving
if entry['event'] in ('Undocked', 'FSDJump', 'SupercruiseEntry'):
this.station = None
this.station_marketid = None
if entry['event'] == 'Embark' and not entry.get('OnStation'):
# If we're embarking OnStation to a Taxi/Dropship we'll also get an
# Undocked event.
this.station = None
this.station_marketid = None
# Only actually change URLs if we are current provider.
if config.get_str('system_provider') == 'eddb':
this.system_link['text'] = this.system
# Only change URL text if we are current provider.
if config.get_str('station_provider') == 'eddb':
this.system_link['text'] = this.system_name
# Do *NOT* set 'url' here, as it's set to a function that will call
# through correctly. We don't want a static string.
this.system_link.update_idletasks()
# But only actually change the URL if we are current station provider.
if config.get_str('station_provider') == 'eddb':
text = this.station
if not text:
if this.station_name:
this.station_link['text'] = this.station_name
else:
if this.system_population is not None and this.system_population > 0:
text = this.STATION_UNDOCKED
this.station_link['text'] = this.STATION_UNDOCKED
else:
text = ''
this.station_link['text'] = ''
this.station_link['text'] = text
# Do *NOT* set 'url' here, as it's set to a function that will call
# through correctly. We don't want a static string.
this.station_link.update_idletasks()
def cmdr_data(data: CAPIData, is_beta: bool) -> Optional[str]:
def cmdr_data(data: CAPIData, is_beta: bool) -> str | None:
"""
Process new CAPI data.
@@ -249,22 +225,22 @@ def cmdr_data(data: CAPIData, is_beta: bool) -> Optional[str]:
this.station_marketid = data['lastStarport']['id']
# Only trust CAPI if these aren't yet set
if not this.system:
this.system = data['lastSystem']['name']
if not this.system_name:
this.system_name = data['lastSystem']['name']
if not this.station and data['commander']['docked']:
this.station = data['lastStarport']['name']
if not this.station_name and data['commander']['docked']:
this.station_name = data['lastStarport']['name']
# Override standard URL functions
if config.get_str('system_provider') == 'eddb':
this.system_link['text'] = this.system
this.system_link['text'] = this.system_name
# Do *NOT* set 'url' here, as it's set to a function that will call
# through correctly. We don't want a static string.
this.system_link.update_idletasks()
if config.get_str('station_provider') == 'eddb':
if data['commander']['docked'] or this.on_foot and this.station:
this.station_link['text'] = this.station
if data['commander']['docked'] or this.on_foot and this.station_name:
this.station_link['text'] = this.station_name
elif data['lastStarport']['name'] and data['lastStarport']['name'] != "":
this.station_link['text'] = this.STATION_UNDOCKED
+128 -81
View File
@@ -82,10 +82,15 @@ class This:
self.odyssey = False
# Track location to add to Journal events
self.systemaddress: Optional[str] = None
self.system_address: Optional[str] = None
self.system_name: Optional[str] = None
self.coordinates: Optional[Tuple] = None
self.body_name: Optional[str] = None
self.body_id: Optional[int] = None
self.body_type: Optional[int] = None
self.station_name: str | None = None
self.station_type: str | None = None
self.station_marketid: str | None = None
# Track Status.json data
self.status_body_name: Optional[str] = None
@@ -117,9 +122,15 @@ class This:
# Tracking UI
self.ui: tk.Frame
self.ui_system_name: tk.Label
self.ui_system_address: tk.Label
self.ui_j_body_name: tk.Label
self.ui_j_body_id: tk.Label
self.ui_j_body_type: tk.Label
self.ui_s_body_name: tk.Label
self.ui_station_name: tk.Label
self.ui_station_type: tk.Label
self.ui_station_marketid: tk.Label
this = This()
@@ -1116,18 +1127,17 @@ class EDDN:
entry['StarSystem'] = system_name
if 'SystemAddress' not in entry:
if this.systemaddress is None:
if this.system_address is None:
logger.warning("this.systemaddress is None, can't add SystemAddress")
return "this.systemaddress is None, can't add SystemAddress"
entry['SystemAddress'] = this.systemaddress
entry['SystemAddress'] = this.system_address
if 'StarPos' not in entry:
# Prefer the passed-in, probably monitor.state version
# Prefer the passed-in version
if system_coordinates is not None:
entry['StarPos'] = system_coordinates
# TODO: Deprecate in-plugin tracking
elif this.coordinates is not None:
entry['StarPos'] = list(this.coordinates)
@@ -1160,7 +1170,7 @@ class EDDN:
#######################################################################
# In this case should add StarPos, but only if the
# SystemAddress of where we think we are matches.
if this.systemaddress is None or this.systemaddress != entry['SystemAddress']:
if this.system_address is None or this.system_address != entry['SystemAddress']:
logger.warning("SystemAddress isn't current location! Can't add augmentations!")
return 'Wrong System! Missed jump ?'
@@ -1202,7 +1212,7 @@ class EDDN:
#######################################################################
# In this case should add StarSystem and StarPos, but only if the
# SystemAddress of where we think we are matches.
if this.systemaddress is None or this.systemaddress != entry['SystemAddress']:
if this.system_address is None or this.system_address != entry['SystemAddress']:
logger.warning("SystemAddress isn't current location! Can't add augmentations!")
return 'Wrong System! Missed jump ?'
@@ -1264,7 +1274,7 @@ class EDDN:
#######################################################################
# In this case should add StarPos, but only if the
# SystemAddress of where we think we are matches.
if this.systemaddress is None or this.systemaddress != entry['SystemAddress']:
if this.system_address is None or this.system_address != entry['SystemAddress']:
logger.warning("SystemAddress isn't current location! Can't add augmentations!")
return 'Wrong System! Missed jump ?'
@@ -1279,6 +1289,8 @@ class EDDN:
logger.warning(f'this.status_body_name was not set properly:'
f' "{this.status_body_name}" ({type(this.status_body_name)})')
# this.status_body_name is available for cross-checks, so try to set
# BodyName and ID.
else:
# In case Frontier add it in
if 'BodyName' not in entry:
@@ -1356,7 +1368,7 @@ class EDDN:
#######################################################################
# In this case should add StarPos, but only if the
# SystemAddress of where we think we are matches.
if this.systemaddress is None or this.systemaddress != entry['SystemAddress']:
if this.system_address is None or this.system_address != entry['SystemAddress']:
logger.warning("SystemAddress isn't current location! Can't add augmentations!")
return 'Wrong System! Missed jump ?'
@@ -1651,7 +1663,7 @@ class EDDN:
#######################################################################
# In this case should add SystemName and StarPos, but only if the
# SystemAddress of where we think we are matches.
if this.systemaddress is None or this.systemaddress != entry['SystemAddress']:
if this.system_address is None or this.system_address != entry['SystemAddress']:
logger.warning("SystemAddress isn't current location! Can't add augmentations!")
return 'Wrong System! Missed jump ?'
@@ -1701,7 +1713,7 @@ class EDDN:
#######################################################################
# In this case should add StarPos, but only if the
# SystemAddress of where we think we are matches.
if this.systemaddress is None or this.systemaddress != entry['SystemAddress']:
if this.system_address is None or this.system_address != entry['SystemAddress']:
logger.warning("SystemAddress isn't current location! Can't add augmentations!")
return 'Wrong System! Missed jump ?'
@@ -1757,7 +1769,7 @@ class EDDN:
#######################################################################
# In this case should add SystemName and StarPos, but only if the
# SystemAddress of where we think we are matches.
if this.systemaddress is None or this.systemaddress != entry['SystemAddress']:
if this.system_address is None or this.system_address != entry['SystemAddress']:
logger.warning("SystemAddress isn't current location! Can't add augmentations!")
return 'Wrong System! Missed jump ?'
@@ -1815,11 +1827,11 @@ class EDDN:
else:
# Horizons order, so use tracked data for cross-check
if this.systemaddress is None or system_name is None or system_starpos is None:
logger.error(f'Location tracking failure: {this.systemaddress=}, {system_name=}, {system_starpos=}')
if this.system_address is None or system_name is None or system_starpos is None:
logger.error(f'Location tracking failure: {this.system_address=}, {system_name=}, {system_starpos=}')
return 'Current location not tracked properly, started after game?'
aug_systemaddress = this.systemaddress
aug_systemaddress = this.system_address
aug_starsystem = system_name
aug_starpos = system_starpos
@@ -1963,23 +1975,75 @@ def plugin_app(parent: tk.Tk) -> Optional[tk.Frame]:
this.ui = tk.Frame(parent)
row = this.ui.grid_size()[1]
#######################################################################
# System
#######################################################################
# SystemName
system_name_label = tk.Label(this.ui, text="J:SystemName:")
system_name_label.grid(row=row, column=0, sticky=tk.W)
this.ui_system_name = tk.Label(this.ui, name='eddn_track_system_name', anchor=tk.W)
this.ui_system_name.grid(row=row, column=1, sticky=tk.E)
row += 1
# SystemAddress
system_address_label = tk.Label(this.ui, text="J:SystemAddress:")
system_address_label.grid(row=row, column=0, sticky=tk.W)
this.ui_system_address = tk.Label(this.ui, name='eddn_track_system_address', anchor=tk.W)
this.ui_system_address.grid(row=row, column=1, sticky=tk.E)
row += 1
#######################################################################
#######################################################################
# Body
#######################################################################
# Body Name from Journal
journal_body_name_label = tk.Label(this.ui, text="J:BodyName:")
journal_body_name_label.grid(row=row, column=0, sticky=tk.W)
this.ui_j_body_name = tk.Label(this.ui, name='eddn_track_j_body_name', anchor=tk.W)
this.ui_j_body_name.grid(row=row, column=1, sticky=tk.E)
row += 1
# Body ID from Journal
journal_body_id_label = tk.Label(this.ui, text="J:BodyID:")
journal_body_id_label.grid(row=row, column=0, sticky=tk.W)
this.ui_j_body_id = tk.Label(this.ui, name='eddn_track_j_body_id', anchor=tk.W)
this.ui_j_body_id.grid(row=row, column=1, sticky=tk.E)
row += 1
# Body Type from Journal
journal_body_type_label = tk.Label(this.ui, text="J:BodyType:")
journal_body_type_label.grid(row=row, column=0, sticky=tk.W)
this.ui_j_body_type = tk.Label(this.ui, name='eddn_track_j_body_type', anchor=tk.W)
this.ui_j_body_type.grid(row=row, column=1, sticky=tk.E)
row += 1
# Body Name from Status.json
status_body_name_label = tk.Label(this.ui, text="S:BodyName:")
status_body_name_label.grid(row=row, column=0, sticky=tk.W)
this.ui_s_body_name = tk.Label(this.ui, name='eddn_track_s_body_name', anchor=tk.W)
this.ui_s_body_name.grid(row=row, column=1, sticky=tk.E)
row += 1
#######################################################################
#######################################################################
# Station
#######################################################################
# Name
status_station_name_label = tk.Label(this.ui, text="J:StationName:")
status_station_name_label.grid(row=row, column=0, sticky=tk.W)
this.ui_station_name = tk.Label(this.ui, name='eddn_track_station_name', anchor=tk.W)
this.ui_station_name.grid(row=row, column=1, sticky=tk.E)
row += 1
# Type
status_station_type_label = tk.Label(this.ui, text="J:StationType:")
status_station_type_label.grid(row=row, column=0, sticky=tk.W)
this.ui_station_type = tk.Label(this.ui, name='eddn_track_station_type', anchor=tk.W)
this.ui_station_type.grid(row=row, column=1, sticky=tk.E)
row += 1
# MarketID
status_station_marketid_label = tk.Label(this.ui, text="J:StationID:")
status_station_marketid_label.grid(row=row, column=0, sticky=tk.W)
this.ui_station_marketid = tk.Label(this.ui, name='eddn_track_station_id', anchor=tk.W)
this.ui_station_marketid.grid(row=row, column=1, sticky=tk.E)
row += 1
#######################################################################
return this.ui
@@ -1991,6 +2055,14 @@ def tracking_ui_update() -> None:
if not config.eddn_tracking_ui:
return
this.ui_system_name['text'] = '≪None≫'
if this.ui_system_name is not None:
this.ui_system_name['text'] = this.system_name
this.ui_system_address['text'] = '≪None≫'
if this.ui_system_address is not None:
this.ui_system_address['text'] = this.system_address
this.ui_j_body_name['text'] = '≪None≫'
if this.body_name is not None:
this.ui_j_body_name['text'] = this.body_name
@@ -1999,10 +2071,26 @@ def tracking_ui_update() -> None:
if this.body_id is not None:
this.ui_j_body_id['text'] = str(this.body_id)
this.ui_j_body_type['text'] = '≪None≫'
if this.body_type is not None:
this.ui_j_body_type['text'] = str(this.body_type)
this.ui_s_body_name['text'] = '≪None≫'
if this.status_body_name is not None:
this.ui_s_body_name['text'] = this.status_body_name
this.ui_station_name['text'] = '≪None≫'
if this.station_name is not None:
this.ui_station_name['text'] = this.station_name
this.ui_station_type['text'] = '≪None≫'
if this.station_type is not None:
this.ui_station_type['text'] = this.station_type
this.ui_station_marketid['text'] = '≪None≫'
if this.station_marketid is not None:
this.ui_station_marketid['text'] = this.station_marketid
this.ui.update_idletasks()
@@ -2208,68 +2296,28 @@ def journal_entry( # noqa: C901, CCR001
entry
)
# Track location
if event_name == 'supercruiseexit':
# For any orbital station we have no way of determining the body
# it orbits:
#
# In-ship Status.json doesn't specify this.
# On-foot Status.json lists the station itself as Body.
# Location for stations (on-foot or in-ship) has station as Body.
# SupercruiseExit (own ship or taxi) lists the station as the Body.
if entry['BodyType'] == 'Station':
this.body_name = None
this.body_id = None
# Copy some state into module-held variables because we might need it
# outside of this function.
this.body_name = state['Body']
this.body_id = state['BodyID']
this.body_type = state['BodyType']
this.coordinates = state['StarPos']
this.system_address = state['SystemAddress']
this.system_name = state['SystemName']
this.station_name = state['StationName']
this.station_type = state['StationType']
this.station_marketid = state['MarketID']
elif event_name in ('location', 'fsdjump', 'docked', 'carrierjump'):
if event_name in ('location', 'carrierjump'):
if entry.get('BodyType') == 'Planet':
this.body_name = entry.get('Body')
this.body_id = entry.get('BodyID')
else:
this.body_name = None
elif event_name == 'fsdjump':
this.body_name = None
this.body_id = None
if 'StarPos' in entry:
this.coordinates = tuple(entry['StarPos'])
elif this.systemaddress != entry.get('SystemAddress'):
this.coordinates = None # Docked event doesn't include coordinates
if 'SystemAddress' not in entry:
logger.warning(f'"location" event without SystemAddress !!!:\n{entry}\n')
# But we'll still *use* the value, because if a 'location' event doesn't
# have this we've still moved and now don't know where and MUST NOT
# continue to use any old value.
# Yes, explicitly state `None` here, so it's crystal clear.
this.systemaddress = entry.get('SystemAddress', None) # type: ignore
if event_name == 'docked':
this.eddn.parent.after(this.eddn.REPLAY_DELAY, this.eddn.sender.queue_check_and_send, False)
elif event_name == 'approachbody':
this.body_name = entry['Body']
this.body_id = entry.get('BodyID')
elif event_name == 'leavebody':
# NB: **NOT** SupercruiseEntry, because we won't get a fresh
# ApproachBody if we don't leave Orbital Cruise and land again.
# *This* is triggered when you go above Orbital Cruise altitude.
# Status.json BodyName clears when the OC/Glide HUD is deactivated.
this.body_name = None
this.body_id = None
if event_name == 'docked':
# Trigger a send/retry of pending EDDN messages
this.eddn.parent.after(this.eddn.REPLAY_DELAY, this.eddn.sender.queue_check_and_send, False)
elif event_name == 'music':
if entry['MusicTrack'] == 'MainMenu':
this.body_name = None
this.body_id = None
this.status_body_name = None
tracking_ui_update()
# Events with their own EDDN schema
if config.get_int('output') & config.OUT_EDDN_SEND_NON_STATION and not state['Captain']:
@@ -2359,9 +2407,10 @@ def journal_entry( # noqa: C901, CCR001
]
# add planet to Docked event for planetary stations if known
if event_name == 'docked' and this.body_name:
entry['Body'] = this.body_name
entry['BodyType'] = 'Planet'
if event_name == 'docked' and state['Body'] is not None:
if state['BodyType'] == 'Planet':
entry['Body'] = state['Body']
entry['BodyType'] = state['BodyType']
# The generic journal schema is for events:
# Docked, FSDJump, Scan, Location, SAASignalsFound, CarrierJump
@@ -2382,7 +2431,7 @@ def journal_entry( # noqa: C901, CCR001
# add mandatory StarSystem and StarPos properties to events
if 'StarSystem' not in entry:
if this.systemaddress is None or this.systemaddress != entry['SystemAddress']:
if this.system_address is None or this.system_address != entry['SystemAddress']:
logger.warning(f"event({entry['event']}) has no StarSystem, but SystemAddress isn't current location")
return "Wrong System! Delayed Scan event?"
@@ -2399,7 +2448,7 @@ def journal_entry( # noqa: C901, CCR001
# Gazelle[TD] reported seeing a lagged Scan event with incorrect
# augmented StarPos: <https://github.com/EDCD/EDMarketConnector/issues/961>
if this.systemaddress is None or this.systemaddress != entry['SystemAddress']:
if this.system_address is None or this.system_address != entry['SystemAddress']:
logger.warning(f"event({entry['event']}) has no StarPos, but SystemAddress isn't current location")
return "Wrong System! Delayed Scan event?"
@@ -2454,8 +2503,6 @@ def journal_entry( # noqa: C901, CCR001
logger.debug(f'Failed exporting {entry["event"]}', exc_info=e)
return str(e)
tracking_ui_update()
return None
@@ -2494,7 +2541,7 @@ def cmdr_data(data: CAPIData, is_beta: bool) -> Optional[str]: # noqa: CCR001
):
this.cmdr_name = cmdr_name
if (data['commander'].get('docked') or (this.on_foot and monitor.station)
if (data['commander'].get('docked') or (this.on_foot and monitor.state['StationName'])
and config.get_int('output') & config.OUT_EDDN_SEND_STATION_DATA):
try:
if this.marketId != data['lastStarport']['id']:
+19 -42
View File
@@ -94,11 +94,11 @@ class This:
self.newgame_docked: bool = False # starting up while docked
self.navbeaconscan: int = 0 # batch up burst of Scan events after NavBeaconScan
self.system_link: tk.Widget | None = None
self.system: tk.Tk | None = None
self.system_name: tk.Tk | None = None
self.system_address: int | None = None # Frontier SystemAddress
self.system_population: int | None = None
self.station_link: tk.Widget | None = None
self.station: str | None = None
self.station_name: str | None = None
self.station_marketid: int | None = None # Frontier MarketID
self.on_foot = False
@@ -186,9 +186,9 @@ def station_url(system_name: str, station_name: str) -> str:
)
# monitor state might think these are gone, but we don't yet
if this.system and this.station:
if this.system_name and this.station_name:
return requests.utils.requote_uri(
f'https://www.edsm.net/en/system?systemName={this.system}&stationName={this.station}'
f'https://www.edsm.net/en/system?systemName={this.system_name}&stationName={this.station_name}'
)
if system_name:
@@ -525,6 +525,11 @@ def journal_entry( # noqa: C901, CCR001
this.game_version = state['GameVersion']
this.game_build = state['GameBuild']
this.system_address = state['SystemAddress']
this.system_name = state['SystemName']
this.system_population = state['SystemPopulation']
this.station_name = state['StationName']
this.station_marketid = state['MarketID']
entry = new_entry
@@ -538,38 +543,10 @@ Station: {station}
state: {state!r}
entry: {entry!r}'''
)
# Always update our system address even if we're not currently the provider for system or station, but dont update
# on events that contain "future" data, such as FSDTarget
if entry['event'] in ('Location', 'Docked', 'CarrierJump', 'FSDJump'):
this.system_address = entry.get('SystemAddress', this.system_address)
this.system = entry.get('StarSystem', this.system)
# We need pop == 0 to set the value so as to clear 'x' in systems with
# no stations.
pop = entry.get('Population')
if pop is not None:
this.system_population = pop
this.station = entry.get('StationName', this.station)
# on_foot station detection
if entry['event'] == 'Location' and entry['BodyType'] == 'Station':
this.station = entry['Body']
this.station_marketid = entry.get('MarketID', this.station_marketid)
# We might pick up StationName in DockingRequested, make sure we clear it if leaving
if entry['event'] in ('Undocked', 'FSDJump', 'SupercruiseEntry'):
this.station = None
this.station_marketid = None
if entry['event'] == 'Embark' and not entry.get('OnStation'):
# If we're embarking OnStation to a Taxi/Dropship we'll also get an
# Undocked event.
this.station = None
this.station_marketid = None
if config.get_str('station_provider') == 'EDSM':
to_set = this.station
if not this.station:
to_set = this.station_name
if not this.station_name:
if this.system_population and this.system_population > 0:
to_set = STATION_UNDOCKED
@@ -578,7 +555,7 @@ entry: {entry!r}'''
if this.station_link:
this.station_link['text'] = to_set
this.station_link['url'] = station_url(str(this.system), str(this.station))
this.station_link['url'] = station_url(str(this.system_name), str(this.station_name))
this.station_link.update_idletasks()
# Update display of 'EDSM Status' image
@@ -685,25 +662,25 @@ def cmdr_data(data: CAPIData, is_beta: bool) -> Optional[str]: # noqa: CCR001
this.station_marketid = data['lastStarport']['id']
# Only trust CAPI if these aren't yet set
if not this.system:
this.system = data['lastSystem']['name']
if not this.system_name:
this.system_name = data['lastSystem']['name']
if not this.station and data['commander']['docked']:
this.station = data['lastStarport']['name']
if not this.station_name and data['commander']['docked']:
this.station_name = data['lastStarport']['name']
# TODO: Fire off the EDSM API call to trigger the callback for the icons
if config.get_str('system_provider') == 'EDSM':
if this.system_link:
this.system_link['text'] = this.system
this.system_link['text'] = this.system_name
# Do *NOT* set 'url' here, as it's set to a function that will call
# through correctly. We don't want a static string.
this.system_link.update_idletasks()
if config.get_str('station_provider') == 'EDSM':
if this.station_link:
if data['commander']['docked'] or this.on_foot and this.station:
this.station_link['text'] = this.station
if data['commander']['docked'] or this.on_foot and this.station_name:
this.station_link['text'] = this.station_name
elif data['lastStarport']['name'] and data['lastStarport']['name'] != "":
this.station_link['text'] = STATION_UNDOCKED
+39 -58
View File
@@ -119,7 +119,7 @@ class This:
# Main window clicks
self.system_link: tk.Widget = None # type: ignore
self.system: Optional[str] = None # type: ignore
self.system_name: Optional[str] = None # type: ignore
self.system_address: Optional[str] = None # type: ignore
self.system_population: Optional[int] = None
self.station_link: tk.Widget = None # type: ignore
@@ -169,10 +169,12 @@ if DEBUG:
def system_url(system_name: str) -> str:
"""Get a URL for the current system."""
if this.system_address:
return requests.utils.requote_uri(f'https://inara.cz/galaxy-starsystem/?search={this.system_address}')
return requests.utils.requote_uri(f'https://inara.cz/galaxy-starsystem/'
f'?search={this.system_address}')
elif system_name:
return requests.utils.requote_uri(f'https://inara.cz/galaxy-starsystem/?search={system_name}')
return requests.utils.requote_uri(f'https://inara.cz/galaxy-starsystem/'
f'?search={system_name}')
return ''
@@ -188,11 +190,13 @@ def station_url(system_name: str, station_name: str) -> str:
:return: A URL to inara for the given system and station
"""
if system_name and station_name:
return requests.utils.requote_uri(f'https://inara.cz/galaxy-station/?search={system_name}%20[{station_name}]')
return requests.utils.requote_uri(f'https://inara.cz/galaxy-station/'
f'?search={system_name}%20[{station_name}]')
# monitor state might think these are gone, but we don't yet
if this.system and this.station:
return requests.utils.requote_uri(f'https://inara.cz/galaxy-station/?search={this.system}%20[{this.station}]')
if this.system_name and this.station:
return requests.utils.requote_uri(f'https://inara.cz/galaxy-station/'
f'?search={this.system_name}%20[{this.station}]')
if system_name:
return system_url(system_name)
@@ -371,6 +375,31 @@ def journal_entry( # noqa: C901, CCR001
:return: str - empty if no error, else error string.
"""
# This overall killswitch check is first in case, e.g. an EDMC bug is
# causing users to spam Inara with 'URL provider' queries, and we want to
# stop that.
should_return: bool
new_entry: Dict[str, Any] = {}
should_return, new_entry = killswitch.check_killswitch('plugins.inara.journal', entry, logger)
if should_return:
plug.show_error(_('Inara disabled. See Log.')) # LANG: INARA support disabled via killswitch
logger.trace('returning due to killswitch match')
return ''
# But then we update all the tracking copies before any other checks,
# because they're relevant for URL providing even if *sending* isn't
# appropriate.
this.on_foot = state['OnFoot']
event_name: str = entry['event']
this.cmdr = cmdr
this.FID = state['FID']
this.multicrew = bool(state['Role'])
this.system_name = state['SystemName']
this.system_address = state['SystemAddress']
this.station = state['StationName']
this.station_marketid = state['MarketID']
if not monitor.is_live_galaxy():
# Since Update 14 on 2022-11-29 Inara only accepts Live data.
if (
@@ -387,15 +416,6 @@ def journal_entry( # noqa: C901, CCR001
return ''
should_return: bool
new_entry: Dict[str, Any] = {}
should_return, new_entry = killswitch.check_killswitch('plugins.inara.journal', entry, logger)
if should_return:
plug.show_error(_('Inara disabled. See Log.')) # LANG: INARA support disabled via killswitch
logger.trace('returning due to killswitch match')
return ''
should_return, new_entry = killswitch.check_killswitch(
f'plugins.inara.journal.event.{entry["event"]}', new_entry, logger
)
@@ -405,12 +425,6 @@ def journal_entry( # noqa: C901, CCR001
return ''
entry = new_entry
this.on_foot = state['OnFoot']
event_name: str = entry['event']
this.cmdr = cmdr
this.FID = state['FID']
this.multicrew = bool(state['Role'])
if event_name == 'LoadGame' or this.newuser:
# clear cached state
if event_name == 'LoadGame':
@@ -431,10 +445,6 @@ def journal_entry( # noqa: C901, CCR001
this.loadout = None
this.fleet = None
this.shipswap = False
this.system = None
this.system_address = None
this.station = None
this.station_marketid = None
elif event_name in ('Resurrect', 'ShipyardBuy', 'ShipyardSell', 'SellShipOnRebuy'):
# Events that mean a significant change in credits, so we should send credits after next "Update"
@@ -443,35 +453,6 @@ def journal_entry( # noqa: C901, CCR001
elif event_name in ('ShipyardNew', 'ShipyardSwap') or (event_name == 'Location' and entry['Docked']):
this.suppress_docked = True
# Always update our system address even if we're not currently the provider for system or station, but dont update
# on events that contain "future" data, such as FSDTarget
if entry['event'] in ('Location', 'Docked', 'CarrierJump', 'FSDJump'):
this.system_address = entry.get('SystemAddress') or this.system_address
this.system = entry.get('StarSystem') or this.system
# We need pop == 0 to set the value so as to clear 'x' in systems with
# no stations.
pop: Optional[int] = entry.get('Population')
if pop is not None:
this.system_population = pop
this.station = entry.get('StationName', this.station)
# on_foot station detection
if entry['event'] == 'Location' and entry['BodyType'] == 'Station':
this.station = entry['Body']
this.station_marketid = entry.get('MarketID', this.station_marketid) or this.station_marketid
# We might pick up StationName in DockingRequested, make sure we clear it if leaving
if event_name in ('Undocked', 'FSDJump', 'SupercruiseEntry'):
this.station = None
this.station_marketid = None
if entry['event'] == 'Embark' and not entry.get('OnStation'):
# If we're embarking OnStation to a Taxi/Dropship we'll also get an
# Undocked event.
this.station = None
this.station_marketid = None
if config.get_int('inara_out') and not is_beta and not this.multicrew and credentials(cmdr):
current_credentials = Credentials(this.cmdr, this.FID, str(credentials(this.cmdr)))
try:
@@ -1158,7 +1139,7 @@ def journal_entry( # noqa: C901, CCR001
to_send_data: Optional[Dict[str, Any]] = {} # This is a glorified sentinel until lower down.
# On Horizons, neither of these exist on TouchDown
star_system_name = entry.get('StarSystem', this.system)
star_system_name = entry.get('StarSystem', this.system_name)
body_name = entry.get('Body', state['Body'] if state['BodyType'] == 'Planet' else None)
if star_system_name is None:
@@ -1377,7 +1358,7 @@ def journal_entry( # noqa: C901, CCR001
# Only actually change URLs if we are current provider.
if config.get_str('system_provider') == 'Inara':
this.system_link['text'] = this.system
this.system_link['text'] = this.system_name
# Do *NOT* set 'url' here, as it's set to a function that will call
# through correctly. We don't want a static string.
this.system_link.update_idletasks()
@@ -1407,14 +1388,14 @@ def cmdr_data(data: CAPIData, is_beta): # noqa: CCR001
this.station_marketid = data['commander']['docked'] and data['lastStarport']['id']
# Only trust CAPI if these aren't yet set
this.system = this.system if this.system else data['lastSystem']['name']
this.system_name = this.system_name if this.system_name else data['lastSystem']['name']
if not this.station and data['commander']['docked']:
this.station = data['lastStarport']['name']
# Override standard URL functions
if config.get_str('system_provider') == 'Inara':
this.system_link['text'] = this.system
this.system_link['text'] = this.system_name
# Do *NOT* set 'url' here, as it's set to a function that will call
# through correctly. We don't want a static string.
this.system_link.update_idletasks()