Skip to content

Commit

Permalink
Where is my ship?
Browse files Browse the repository at this point in the history
See issue #224
  • Loading branch information
lekeno committed Apr 21, 2019
1 parent 2466bbe commit 9141c10
Show file tree
Hide file tree
Showing 9 changed files with 308 additions and 5 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,4 @@ edr/data/cmdrsdex.0.5.0.beta.3.json
edr/private/fbaa.p
edr/design notes.txt
*.p
edr/db/fleet
5 changes: 5 additions & 0 deletions edr/edentities.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import edreconbox
import edrinventory
from edri18n import _, _c
import edrfleet
EDRLOG = edrlog.EDRLog()

class EDRCrew(object):
Expand Down Expand Up @@ -658,6 +659,7 @@ def __init__(self, name=None):
self.planetary_destination = None
self.recon_box = edreconbox.EDReconBox()
self.inventory = edrinventory.EDRInventory()
self.fleet = edrfleet.EDRFleet()

def __repr__(self):
return str(self.__dict__)
Expand Down Expand Up @@ -977,3 +979,6 @@ def attacked(self, target):
EDRLOG.log(u"SLF attacked but player had none", "WARNING")
elif target == "You":
self.piloted_vehicle.attacked()

def update_fleet(self, stored_ships_entry):
self.fleet.update(stored_ships_entry)
24 changes: 23 additions & 1 deletion edr/edrclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -1263,6 +1263,28 @@ def where(self, cmdr_name):
except edrserver.CommsJammedError:
self.__commsjammed()

def where_ship(self, name_or_type):
results = self.player.fleet.where(name_or_type)
if results:
hits = []
random.shuffle(results)
in_clipboard = False
for hit in results:
transit = _(u" @ {}").format(edtime.EDTime.t_plus_py(hit[3])) if hit[3] else u""
if hit[0]:
hits.append(_(u"'{}' ({}): {}{}").format(hit[0], hit[1], hit[2], transit))
else:
hits.append(_(u"{}: {}{}").format(hit[1], hit[2], transit))
if not in_clipboard and hit[2]:
clippy.copy(hit[2])
in_clipboard = True
self.__notify(_(u"Ship locator"), hits, clear_before = True)
elif results == False:
self.__notify(_(u"Ship locator"), [_(u"No info about your fleet."), _(u"Visit a shipyard to update your fleet info.")], clear_before = True)
else:
self.__notify(_(u"Ship locator"), [_(u"Couldn't find anything")], clear_before = True)


def outlaws(self):
try:
return self._opponents(EDROpponents.OUTLAWS)
Expand Down Expand Up @@ -1534,7 +1556,7 @@ def __staoi_found(self, reference, radius, sc, soi_checker, result):
pretty_sc_dist = _(u"{dist}LS").format(dist=int(sc_distance))
details.append(_(u"{system}, {dist}").format(system=result['name'], dist=pretty_dist))
details.append(_(u"{station} ({type}), {sc_dist}").format(station=result['station']['name'], type=result['station']['type'], sc_dist=pretty_sc_dist))
details.append(_(u"as of {date}").format(date=result['station']['updateTime']['information']))
details.append(_(u"as of {date} {ci}").format(date=result['station']['updateTime']['information'],ci=result.get('comment', '')))
self.status = u"{item}: {system}, {dist} - {station} ({type}), {sc_dist}".format(item=soi_checker.name, system=result['name'], dist=pretty_dist, station=result['station']['name'], type=result['station']['type'], sc_dist=pretty_sc_dist)
clippy.copy(result["name"])
else:
Expand Down
208 changes: 208 additions & 0 deletions edr/edrfleet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
import os
import sqlite3
import math

from edvehicles import EDVehicleFactory
import edtime

class EDRFleet(object):

SHIP_TYPE_LUT = {
"fdl": "ferdelance",
"cobra": "cobramkiii",
"t6": "type6",
"t7": "type7",
"t9": "type9",
"t10": "type9_military",
"aspx": "asp",
"clipper": "empire_trader",
"dropship": "federation_dropship",
"beluga": "belugaliner",
"conda": "anaconda",
"corvette": "federation_corvette",
"dbs": "diamondback",
"courier": "empira_courier",
"dbx": "diamondbackxl",
"fas": "federation_dropship_mkii",
"fgs": "federation_gunship",
"gunship": "federation_gunship",
"viper iv": "viper_mkiv",
"viper 4": "viper_mkiv",
"cobra iv": "cobramkiv",
"cobra 4": "cobramkiv",
"keelie": "independant_trader",
"keelback": "independant_trader",
"asps": "asp_scout",
"chieftain": "typex",
"chief": "typex",
"crusader": "typex_2",
"challenger": "typex_3",
"krait": "krait_mkii",
"phantom": "krait_light",
}


def __init__(self):
path = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'db/fleet')
self.db = sqlite3.connect(path) # TODO parameterize
cursor = self.db.cursor()
cursor.execute('''CREATE TABLE IF NOT EXISTS
ships(id INTEGER PRIMARY KEY, type TEXT, localised TEXT, name TEXT,
star_system TEXT, ship_market_id INTEGER, value INTEGER, hot INTEGER, piloted INTEGER DEFAULT 0, eta INTEGER DEFAULT 0)''')
cursor.execute('''CREATE TABLE IF NOT EXISTS
transits(id INTEGER PRIMARY KEY AUTOINCREMENT, ship_id INTEGER, eta INTEGER, source_system TEXT,
destination_system TEXT, source_market_id INTEGER, destination_market_id INTEGER)''')
self.db.commit()

def update(self, event):
local_system = event.get("StarSystem", None)
local_station = event.get("StationName", None)
local_market_id = event.get("MarketID", None)
if not local_station or not local_system or not local_market_id:
return

here = event.get("ShipsHere", [])
try:
cursor = self.db.cursor()
cursor.execute('DROP TABLE ships')
cursor.execute('''CREATE TABLE
ships(id INTEGER PRIMARY KEY, type TEXT, localised TEXT, name TEXT,
star_system TEXT, ship_market_id INTEGER, value INTEGER, hot INTEGER, piloted INTEGER DEFAULT 0, eta INTEGER DEFAULT 0)''')
self.db.commit()
for stored_ship in here:
ship_id = stored_ship.get("ShipID", None)
ship_type = stored_ship.get("ShipType", "").lower()
name = stored_ship.get("Name", "").lower()
localised_type = stored_ship.get("ShipType_Localised", ship_type).lower()
value = stored_ship.get("Value", None)
hot = 1 if stored_ship.get("hot", False) else 0
self.db.execute('''INSERT INTO ships(id, type, localised, name, star_system, ship_market_id, value, hot)
VALUES(?,?,?,?,?,?,?,?)''', (ship_id, ship_type, localised_type, name, local_system, local_market_id, value, hot))

remote = event.get("ShipsRemote", [])
for stored_ship in remote:
system = stored_ship.get("StarSystem", "").lower()
market_id = stored_ship.get("ShipMarketID", None)
ship_id = stored_ship.get("ShipID", None)
ship_type = stored_ship.get("ShipType", "").lower()
name = stored_ship.get("Name", "").lower()
localised_type = stored_ship.get("ShipType_Localised", ship_type).lower()
value = stored_ship.get("Value", None)
hot = 1 if stored_ship.get("hot", False) else 0
self.db.execute('''INSERT INTO ships(id, type, localised, name, star_system, ship_market_id, value, hot)
VALUES(?,?,?,?,?,?,?,?)''', (ship_id, ship_type, localised_type, name, system, market_id, value, hot))
self.db.commit()
self.__update()
except sqlite3.IntegrityError:
pass

def where(self, type_or_name):
self.__update()
ship_type = self.SHIP_TYPE_LUT.get(type_or_name.lower(), type_or_name)
check = self.db.execute("SELECT id from ships limit 1")
if not check.fetchone():
return False
cursor = self.db.execute('SELECT name, localised, star_system, eta FROM ships WHERE (type=? OR name=? OR localised=?) and piloted=0', (ship_type.lower(), type_or_name.lower(), type_or_name.lower(),))
return cursor.fetchall()

def sell(self, sell_event):
if sell_event.get("event", None) not in ["ShipyardSell", "SellShipOnREbuy"]:
return
self.__sold(sell_event["SellShipID"])

def buy(self, buy_event, star_system, storing_ship_name):
if buy_event.get("event", None) != "ShipyardBuy":
return

market_id = buy_event.get("MarketID", None)
if buy_event.get("StoreShipID", None):
storing_ship_id = buy_event["StoreShipID"]
ship_type = buy_event["StoreOldShip"].lower()
localised = EDVehicleFactory.canonicalize(ship_type)
self.db.execute('''INSERT INTO ships(id, type, localised, name, star_system, ship_market_id, value, hot)
VALUES(?,?,?,?,?,?,?,?)''', (storing_ship_id, ship_type, localised, storing_ship_name, star_system, market_id, 0, 0))
self.db.execute('DELETE from transits WHERE ship_id=?', (storing_ship_id, ))
self.db.commit()
elif buy_event.get("SellShipID", None):
self.__sold(buy_event["SellShipID"])

# TODO fix the no info on your fleet when there is some

def new(self, new_event, star_system):
if new_event.get("event", None) != "ShipyardNew":
return
ship_id = new_event.get("NewShipID", None)
ship_type = new_event.get("ShipType", "").lower()
name = ""
localised_type = new_event.get("ShipType_Localised", ship_type).lower()
value = 0
hot = 0
piloted = 1
market_id = None
self.db.execute('''INSERT INTO ships(id, type, localised, name, star_system, ship_market_id, value, hot, piloted)
VALUES(?,?,?,?,?,?,?,?,?)''', (ship_id, ship_type, localised_type, name, star_system, market_id, value, hot, piloted))

def __sold(self, ship_id):
self.db.execute('DELETE from ships WHERE id=?', (ship_id, ))
self.db.execute('DELETE from transits WHERE ship_id=?', (ship_id, ))
self.db.commit()

def rename(self, rename_event):
if rename_event.get("event", None) != "SetUserShipName":
return

ship_id = rename_event["ShipID"]
ship_name = rename_event["UserShipName"]
self.db.execute('UPDATE ships SET piloted=0 WHERE piloted=1')
self.db.execute('UPDATE ships SET name=?, piloted=1 WHERE id=?', (ship_name, ship_id))
self.db.commit()

def swap(self, swap_event, star_system, storing_ship_name):
if swap_event.get("event", None) != "ShipyardSwap":
return

if "SellShipID" in swap_event:
self.__sold(swap_event["SellShipID"])
else:
storing_ship_id = swap_event.get("StoreShipID", None)
ship_type = swap_event.get("StoreOldShip", None).lower()
localised = EDVehicleFactory.canonicalize(ship_type)
market_id = swap_event.get("MarketID", None)
self.db.execute('''INSERT INTO ships(id, type, localised, name, star_system, ship_market_id, value, hot)
VALUES(?,?,?,?,?,?,?,?)''', (storing_ship_id, ship_type, localised, storing_ship_name, star_system, market_id, 0, 0))
self.db.execute('DELETE from transits WHERE ship_id=?', (storing_ship_id, ))

piloting_ship_id = swap_event.get("ShipID", None)
self.db.execute('UPDATE ships SET ship_market_id="", star_system="", piloted=1, eta=0 WHERE id=?', (piloting_ship_id,))
self.db.execute('DELETE from transits WHERE ship_id=?', (piloting_ship_id, ))
self.db.commit()


def transfer(self, transfer_event, dst_system, dst_market_id=""):
if transfer_event.get("event", None) != "ShipyardTransfer":
return

ship_id = transfer_event.get("ShipID", None)
src_system = transfer_event.get("System", None)
src_market_id = transfer_event.get("MarketID", None)
distance = transfer_event.get("Distance", None)
eta = edtime.EDTime.py_epoch_now() + int(math.ceil(distance * 9.75 + 300)) #TODO refactor, 1 more copy of this in edrsystems
self.db.execute('DELETE from transits WHERE ship_id=?', (ship_id, ))
self.db.execute('''INSERT INTO transits(ship_id, eta, source_system, source_market_id, destination_system, destination_market_id)
VALUES (?,?,?,?,?,?)''', (ship_id, eta, src_system, src_market_id, dst_system, dst_market_id))
self.db.execute('UPDATE ships SET ship_market_id=?, star_system=?, piloted=0, eta=? WHERE id=?', (dst_market_id, dst_system, eta, ship_id, ))
self.db.commit()
self.__update()

def __update(self):
now = edtime.EDTime.py_epoch_now()
transits = self.db.execute('SELECT id, ship_id, destination_system, destination_market_id FROM transits WHERE eta<=?', (now,))
for transit in transits:
self.db.execute('UPDATE ships SET star_system=?, ship_market_id=?, eta=0 WHERE id=?', (transit[2], transit[3], transit[1],))
self.db.execute('DELETE from transits WHERE id=?', (transit[0],))

now = edtime.EDTime.py_epoch_now()
transits = self.db.execute('SELECT id, ship_id, destination_system, destination_market_id, eta FROM transits WHERE eta>?', (now,))
for transit in transits:
self.db.execute('UPDATE ships SET star_system=?, ship_market_id=?, eta=? WHERE id=?', (transit[2], transit[3], transit[4], transit[1],))
self.db.commit()
9 changes: 9 additions & 0 deletions edr/edtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ def t_minus(js_epoch_then, short=False):
return _c(u"short notation for t-minus|-{}").format(EDTime.pretty_print_timespan(ago, short=True))
# Translators: this is to show how long ago an event took place, keep it short, e.g. T-{} would show something like T-3H
return u"T-{}".format(EDTime.pretty_print_timespan(ago))

@staticmethod
def t_plus_py(py_epoch_later, short=False):
ahead = int(py_epoch_later - EDTime.py_epoch_now())
if short:
# Translators: this is to show how long ahead an event will take place, keep it ultra-short, e.g. +{} would show something like +3H
return _c(u"short notation for t-plus|+{}").format(EDTime.pretty_print_timespan(ahead, short=True))
# Translators: this is to show how long ahead an event will take place, keep it short, e.g. T+{} would show something like T+3H
return u"T+{}".format(EDTime.pretty_print_timespan(ahead))

@staticmethod
def pretty_print_timespan(timespan, short=False, verbose=False):
Expand Down
13 changes: 11 additions & 2 deletions edr/edvehicles.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,18 @@ def update_from_loadout(self, event):
return
modules = event['Modules']
for module in modules:
health = modules[module]['Health'] * 100.0 if 'Health' in modules[module] else None
self.subsystem_health(modules[module].get('Item', None), health)
health = module['Health'] * 100.0 if 'Health' in module else None
self.subsystem_health(module.get('Item', None), health)

def update_name(self, event):
other_id = event.get("ShipID", None)
other_type = EDVehicleFactory.canonicalize(event.get("Ship", "unknown"))
if other_id != self.id or other_type != self.type:
EDRLOG.log(u"Mismatch between ID ({} vs {}) and/or Type ({} vs. {}), can't update name/identity".format(self.id, other_id, self.type, other_type), "WARNING")
return
self.identity = event.get('UserShipId', None)
self.name = event.get('UserShipName', None)

def update_attitude(self, attitude):
self.attitude.update(attitude)

Expand Down
11 changes: 11 additions & 0 deletions edr/helpcontent.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class HelpContent(object):
_(u" - !help sqdrdex: tag other commanders as ally or enemy of your squadron"),
_(u" - !help nearby: commands to find services near you or a specific system, e.g. interstellar factors"),
_(u" - !help search: find the best spots to obtain specific resources, e.g. adaptive encryptors capture"),
_(u" - !help ship: find out where you've parked your ships"),
_(u" - !help config: configuration options"),
u"⚶",
_(u"Send !clear in chat to clear everything on the overlay.")
Expand Down Expand Up @@ -229,6 +230,16 @@ class HelpContent(object):
_(u"Send !clear in chat to clear everything on the overlay.")
]
},
"ship": {
"header": _(u"Find where you parked your ship"),
"details": [
_(u" - '!ship name_or_type' where name_or_type is either a ship name or type."),
_(u" - '!ship fdl' will show where your Fer-de-Lance ships are parked."),
_(u" - '!ship In Front of Things' will show where your ship(s) named 'In Front of Things' are."),
u"⚶",
_(u"Send !clear in chat to clear everything on the overlay.")
]
},
"config": {
"header": _(u"Configuration options"),
"details": [
Expand Down
Loading

0 comments on commit 9141c10

Please sign in to comment.