Skip to content

Commit

Permalink
Merge branch 'release/3.1.0-a1'
Browse files Browse the repository at this point in the history
  • Loading branch information
aussig committed Apr 30, 2023
2 parents 7ca31dc + f2b2e9d commit c095a26
Show file tree
Hide file tree
Showing 22 changed files with 459 additions and 104 deletions.
28 changes: 27 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,36 @@
# Change Log

## v3.1.0-a1 - 2023-04-30

### New Features:

* Thargoid War kills are now tracked for each vessel type: `💀 (kills)`. But **please be aware**: BGS-Tally will only count a kill if it is logged in your game journal. This reliably happens if you solo kill a Thargoid, and sometimes happens when you kill in a Team or with others. However, when not solo-killing, this is **highly unreliable**. Please don't file a bug if you find your kills aren't being tallied when fighting with other CMDRs in the instance.
* Thargoid War Search and Rescue collection and hand-in tracking. BGS-Tally now tracks where you pick up occupied and damaged escape pods ⚰️, black boxes ⬛ and tissue samples 🌱. You can hand them in anywhere, but they are tallied in the system they were collected.
* You can now delete CMDRs from the CMDR target list history.
* Targets older than 90 days are automatically removed from the CMDR target list history.
* When a friend request is received from another player, their details are looked up on Inara and they are added to the target log. Note that the squadron ID and legal status will be shown as '----' as that information is not available for friend requests.
* Carrier jump reporting implemented, automatically reporting your carrier jumps (and cancelled jumps) to a Discord channel of your choice.

### Changes:

* Thargoid War massacre missions are now labelled slightly differently - `💀 (missions)` - in line with the labelling for kills - `💀 (kills)`.
* Posting information on Discord now goes to a separate 'CMDR Information' channel, if you configure one. It will fall back to using the BGS channel.

### Bug Fixes:

* BGS-Tally was crashing on load when running on Linux. This is now fixed.

### API Changes ([v1.1](https://studio-ws.apicur.io/sharing/281a84ad-dca9-42da-a08b-84e4b9af1b7e)):

* `/activities` endpoint: Thargoid war kills now included in `systems/[system]/twkills`
* `/activities` endpoint: Thargoid search and rescue counts now included in `systems/[system]/twsandr`


## v3.0.2 - 2023-04-11

### Bug Fixes:

* Fix crashing bug for new clean installs.
* Fix crashing bug which was affecting some CMDRs, stopping Discord posting. Unfortunate side effect was that it also stopped auto-updating, so this version will have to be installed manually.


## v3.0.1 - 2023-04-11
Expand Down
Binary file added assets/icon_tw_kills.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icon_tw_mass_missions.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icon_tw_sr_bbs.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icon_tw_sr_pods.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icon_tw_sr_tissue.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
132 changes: 124 additions & 8 deletions bgstally/activity.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@
CZ_GROUND_LOW_CB_MAX = 5000
CZ_GROUND_MED_CB_MAX = 38000

TW_CBS = {65000: 's', 75000: 's', 6500000: 'c', 20000000: 'b', 25000000: 'o', 34000000: 'm', 50000000: 'h'}


class Activity:
"""
Expand Down Expand Up @@ -148,7 +150,7 @@ def get_ordered_systems(self):
def clear_activity(self, mission_log: MissionLog):
"""
Clear down all activity. If there is a currently active mission in a system or it's the current system the player is in,
only zero the activity, otherwise delete the system completely.
or the system has had search and rescue items collected there, only zero the activity, otherwise delete the system completely.
"""
self.dirty = True
mission_systems = mission_log.get_active_systems()
Expand All @@ -158,12 +160,16 @@ def clear_activity(self, mission_log: MissionLog):
system = self.systems[system_address]
# Note that the missions log historically stores system name so we check for that, not system address.
# Potential for very rare bug here for systems with duplicate names.
if system['System'] in mission_systems or self.bgstally.state.current_system_id == system_address:
# The system has a current mission, or it's the current system - zero, don't delete
if system['System'] in mission_systems or \
self.bgstally.state.current_system_id == system_address or \
sum(int(d['scooped']) for d in system['TWSandR'].values()) > 0:
# The system has a current mission, or it's the current system, or it has TWSandR scoops - zero, don't delete
for faction_name, faction_data in system['Factions'].items():
system['Factions'][faction_name] = self._get_new_faction_data(faction_name, faction_data['FactionState'])
system['TWKills'] = self._get_new_tw_kills_data()
# Note: system['TWSandR'] data is carried forward
else:
# No current missions, delete the whole system
# Delete the whole system
del self.systems[system_address]


Expand Down Expand Up @@ -192,6 +198,8 @@ def system_entered(self, journal_entry: Dict, state: State):
current_system = self._get_new_system_data(journal_entry['StarSystem'], journal_entry['SystemAddress'], {})
self.systems[str(journal_entry['SystemAddress'])] = current_system

self._update_system_data(current_system)

for faction in journal_entry['Factions']:
if faction['Name'] == "Pilots' Federation Local Branch": continue

Expand Down Expand Up @@ -503,10 +511,18 @@ def cb_received(self, journal_entry: Dict, state: State):
"""
Handle a combat bond received for a kill
"""
if state.last_settlement_approached == {}: return

current_system = self.systems.get(state.current_system_id)
if not current_system: return

# Check for Thargoid Kill
if journal_entry.get('VictimFaction') == "$faction_Thargoid;":
tw_ship:str = TW_CBS.get(journal_entry['Reward'])
if tw_ship: current_system['TWKills'][tw_ship] += 1
return

# Otherwise, must be on-ground for CB kill tracking
if state.last_settlement_approached == {}: return

self.dirty = True

timedifference = datetime.strptime(journal_entry['timestamp'], "%Y-%m-%dT%H:%M:%SZ") - datetime.strptime(state.last_settlement_approached['timestamp'], "%Y-%m-%dT%H:%M:%SZ")
Expand Down Expand Up @@ -571,17 +587,92 @@ def cb_received(self, journal_entry: Dict, state: State):
self.recalculate_zero_activity()


def collect_cargo(self, journal_entry: dict, state: State):
"""
Handle cargo collection for certain cargo types
"""
current_system = self.systems.get(state.current_system_id)
if not current_system: return

key:str = None

match journal_entry.get('Type'):
case 'damagedescapepod': key = 'dp'
case 'occupiedcryopod': key = 'op'
case 'usscargoblackbox': key = 'bb'

if key is None: return

current_system['TWSandR'][key]['scooped'] += 1
self.dirty = True


def search_and_rescue(self, journal_entry: dict, state: State):
"""
Handle search and rescue hand-in
"""
key:str = None

match journal_entry('Name'):
case 'damagedescapepod': key = 'dp'
case 'occupiedcryopod': key = 'op'
case 'usscargoblackbox': key = 'bb'

if key is None: return

# S&R can be handed in in any system, but the effect counts for the system the items were collected in. However,
# we have no way of knowing exactly which items were handed in, so just iterate through all our known systems
# looking for previously scooped cargo of the correct type.

count:int = int(journal_entry.get('Count', 0))

for system in self.systems.values():
if count <= 0: break # Finish when we've accounted for all items

allocatable:int = min(count, system['TWSandR'][key]['scooped'])
if allocatable > 0:
system['TWSandR'][key]['scooped'] -= allocatable
system['TWSandR'][key]['delivered'] += allocatable
count -= allocatable
self.dirty = True

# count can end up > 0 here - i.e. more S&R handed in than we originally logged as scooped. Ignore, as we don't know
# where it originally came from


def player_resurrected(self):
"""
Clear down any logged cargo on resurrect
"""
for system in self.systems.values():
system['TWSandR'] = self._get_new_tw_sandr_data()

self.dirty = True


def recalculate_zero_activity(self):
"""
For efficiency at display time, we store whether each system has had any activity in the data structure
"""
for system in self.systems.values():
self._update_system_data(system)
system['zero_system_activity'] = True

for faction_data in system['Factions'].values():
self._update_faction_data(faction_data)
if not self._is_faction_data_zero(faction_data):
system['zero_system_activity'] = False

if system['zero_system_activity'] == False: continue

if sum(system['TWKills'].values()) > 0: system['zero_system_activity'] = False

if system['zero_system_activity'] == False: continue

if sum(int(d['delivered']) for d in system['TWSandR'].values()) > 0: system['zero_system_activity'] = False

if system['zero_system_activity'] == False: continue


#
# Private functions
Expand All @@ -594,7 +685,9 @@ def _get_new_system_data(self, system_name: str, system_address: str, faction_da
return {'System': system_name,
'SystemAddress': system_address,
'zero_system_activity': True,
'Factions': faction_data}
'Factions': faction_data,
'TWKills': self._get_new_tw_kills_data(),
'TWSandR': self._get_new_tw_sandr_data()}


def _get_new_faction_data(self, faction_name, faction_state):
Expand Down Expand Up @@ -622,6 +715,29 @@ def _get_new_tw_station_data(self, station_name):
'massacre': {'s': {'count': 0, 'sum': 0}, 'c': {'count': 0, 'sum': 0}, 'b': {'count': 0, 'sum': 0}, 'm': {'count': 0, 'sum': 0}, 'h': {'count': 0, 'sum': 0}, 'o': {'count': 0, 'sum': 0}}}


def _get_new_tw_kills_data(self):
"""
Get a new data structure for storing Thargoid War Kills
"""
return {'s': 0, 'c': 0, 'b': 0, 'm': 0, 'h': 0, 'o': 0}


def _get_new_tw_sandr_data(self):
"""
Get a new data structure for storing Thargoid War Search and Rescue
"""
return {'dp': {'scooped': 0, 'delivered': 0}, 'op': {'scooped': 0, 'delivered': 0}, 'bb': {'scooped': 0, 'delivered': 0}, 't': {'scooped': 0, 'delivered': 0}}


def _update_system_data(self, system_data:dict):
"""
Update system data structure for elements not present in previous versions of plugin
"""
# From < v3.1.0 to 3.1.0
if not 'TWKills' in system_data: system_data['TWKills'] = self._get_new_tw_kills_data()
if not 'TWSandR' in system_data: system_data['TWSandR'] = self._get_new_tw_sandr_data()


def _update_faction_data(self, faction_data: Dict, faction_state: str = None):
"""
Update faction data structure for elements not present in previous versions of plugin
Expand Down Expand Up @@ -660,7 +776,7 @@ def _update_faction_data(self, faction_data: Dict, faction_state: str = None):
station['cargo'] = {'count': 0, 'sum': station['cargo']}
if not type(station.get('massacre')) == dict:
station['massacre'] = {'s': {'count': 0, 'sum': 0}, 'c': {'count': 0, 'sum': 0}, 'b': {'count': 0, 'sum': 0}, 'm': {'count': 0, 'sum': 0}, 'h': {'count': 0, 'sum': 0}, 'o': {'count': 0, 'sum': 0}}
# From < 2.3.0 to 2.3.0
# From < 3.0.0 to 3.0.0
if not 'GroundMurdered' in faction_data: faction_data['GroundMurdered'] = 0
if not 'TradeBuy' in faction_data:
faction_data['TradeBuy'] = [{'items': 0, 'value': 0}, {'items': 0, 'value': 0}, {'items': 0, 'value': 0}, {'items': 0, 'value': 0}]
Expand Down
5 changes: 3 additions & 2 deletions bgstally/api.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@

from json import JSONDecodeError
from queue import Queue
from re import match
from threading import Thread
from time import sleep

import semantic_version
from requests import JSONDecodeError, Response
from requests import Response

from bgstally.constants import RequestMethod
from bgstally.debug import Debug
from bgstally.requestmanager import BGSTallyRequest
from bgstally.utils import get_by_path

API_VERSION = "1.0.0"
API_VERSION = "1.1.0"

ENDPOINT_ACTIVITIES = "activities" # Used as both the dict key and default path
ENDPOINT_DISCOVERY = "discovery" # Used as the path
Expand Down
45 changes: 44 additions & 1 deletion bgstally/apimanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ def _build_api_activity(self, activity:Activity, cmdr:str):
api_system:dict = {
'name': system.get('System', ""),
'address': system.get('SystemAddress', ""),
'factions': []
'factions': [],
'twkills': {}
}

for faction in system.get('Factions', {}).values():
Expand Down Expand Up @@ -198,6 +199,24 @@ def _build_api_activity(self, activity:Activity, cmdr:str):

api_system['factions'].append(api_faction)

if sum(system.get('TWKills', {}).values()) > 0:
api_system['twkills'] = {
'basilisk': system['TWKills']['b'],
'cyclops': system['TWKills']['c'],
'hydra': system['TWKills']['h'],
'medusa': system['TWKills']['m'],
'orthrus': system['TWKills']['o'],
'scout': system['TWKills']['s']
}

if sum(int(d['delivered']) for d in system.get('TWSandR', {}).values()) > 0:
api_system['twsandr'] = {
'damagedpods': system['TWSandR']['dp']['delivered'],
'occupiedpods': system['TWSandR']['op']['delivered'],
'blackboxes': system['TWSandR']['bb']['delivered'],
'tissuesamples': system['TWSandR']['t']['delivered']
}

api_activity['systems'].append(api_system)

return api_activity
Expand Down Expand Up @@ -233,3 +252,27 @@ def _build_api_event(self, event:dict, activity:Activity, cmdr:str):
event['Demand'] = market_data.get('Demand', 0)

return event


def _filter_localised(self, d: dict[str, any]) -> dict[str, any]:
"""
Recursively remove any dict keys with names ending `_Localised` from a dict.
:param d: dict to filter keys of.
:return: The filtered dict.
"""
filtered: dict[str, any] = dict()
for k, v in d.items():
if k.endswith('_Localised'):
pass

elif hasattr(v, 'items'): # dict -> recurse
filtered[k] = self._filter_localised(v)

elif isinstance(v, list): # list of dicts -> recurse
filtered[k] = [self._filter_localised(x) if hasattr(x, 'items') else x for x in v]

else:
filtered[k] = v

return filtered
24 changes: 24 additions & 0 deletions bgstally/bgstally.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,19 @@ def journal_entry(self, cmdr, is_beta, system, station, entry, state):
activity.settlement_approached(entry, self.state)
dirty = True

case 'CarrierJumpCancelled':
self.fleet_carrier.jump_cancelled()

case 'CarrierJumpRequest':
self.fleet_carrier.jump_requested(entry)

case 'CarrierStats':
self.fleet_carrier.stats_received(entry)

case 'CollectCargo':
activity.collect_cargo(entry, self.state)
dirty = True

case 'CommitCrime':
activity.crime_committed(entry, self.state)
dirty = True
Expand All @@ -120,6 +133,9 @@ def journal_entry(self, cmdr, is_beta, system, station, entry, state):
activity.cb_received(entry, self.state)
dirty = True

case 'Friends' if entry.get('Status') == "Requested":
self.target_log.friend_request(entry, system)

case 'Location' | 'StartUp' if entry.get('Docked') == True:
self.state.station_type = entry['StationType']
dirty = True
Expand Down Expand Up @@ -160,6 +176,14 @@ def journal_entry(self, cmdr, is_beta, system, station, entry, state):
activity.cb_redeemed(entry, self.state)
dirty = True

case 'Resurrect':
activity.player_resurrected()
dirty = True

case 'SearchAndRescue':
activity.search_and_rescue(entry, self.state)
dirty = True

case 'SellExplorationData' | 'MultiSellExplorationData':
activity.exploration_data_sold(entry, self.state)
dirty = True
Expand Down
6 changes: 4 additions & 2 deletions bgstally/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@ class UpdateUIPolicy(Enum):

class DiscordChannel(Enum):
BGS = 0
FLEETCARRIER = 1
THARGOIDWAR = 2
CMDR_INFORMATION = 1
FLEETCARRIER_MATERIALS = 2
FLEETCARRIER_OPERATIONS = 3
THARGOIDWAR = 4


class MaterialsCategory(Enum):
Expand Down
Loading

0 comments on commit c095a26

Please sign in to comment.