public static List <MicroResourceAmount> ReadMicroResources(string key, IDictionary <string, object> data, string categoryEdName = null) { var result = new List <MicroResourceAmount>(); if (data.TryGetValue(key, out object val)) { if (val is List <object> listVal) { foreach (IDictionary <string, object> microResourceVal in listVal) { var edname = JsonParsing.getString(microResourceVal, "Name"); var fallbackName = JsonParsing.getString(microResourceVal, "Name_Localised"); categoryEdName = JsonParsing.getString(microResourceVal, "Type") ?? categoryEdName ?? MicroResourceCategory.Unknown.edname; var resource = MicroResource.FromEDName(edname, fallbackName, categoryEdName); var ownerId = JsonParsing.getOptionalInt(microResourceVal, "OwnerID"); var missionId = JsonParsing.getOptionalDecimal(microResourceVal, "MissionID"); var amount = JsonParsing.getInt(microResourceVal, "Count"); result.Add(new MicroResourceAmount(resource, ownerId, missionId, amount)); } } } return(result); }
private static void PreserveSystemProperties(StarSystem updatedSystem, IDictionary <string, object> oldStarSystem) { // Carry over StarSystem properties that we want to preserve updatedSystem.totalbodies = JsonParsing.getOptionalInt(oldStarSystem, "discoverableBodies") ?? 0; if (oldStarSystem.TryGetValue("visitLog", out object visitLogObj)) { // Visits should sync from EDSM, but in case there is a problem with the connection we will also seed back in our old star system visit data if (visitLogObj is List <object> oldVisitLog) { foreach (DateTime visit in oldVisitLog) { // The SortedSet<T> class does not accept duplicate elements so we can safely add timestamps which may be duplicates of visits already reported from EDSM. // If an item is already in the set, processing continues and no exception is thrown. updatedSystem.visitLog.Add(visit); } } } }
public Status ParseStatusEntry(string line) { Status status = new Status(); try { Match match = JsonRegex.Match(line); if (match.Success) { IDictionary <string, object> data = Deserializtion.DeserializeData(line); // Every status event has a timestamp field status.timestamp = DateTime.UtcNow; try { status.timestamp = JsonParsing.getDateTime("timestamp", data); } catch { Logging.Warn("Status without timestamp; using current time"); } status.flags = (Status.Flags)(JsonParsing.getOptionalLong(data, "Flags") ?? 0); if (status.flags == Status.Flags.None) { // No flags are set. We aren't in game. return(status); } data.TryGetValue("Pips", out object val); List <long> pips = ((List <object>)val)?.Cast <long>()?.ToList(); // The 'TryGetValue' function returns these values as type 'object<long>' status.pips_sys = pips != null ? ((decimal?)pips[0] / 2) : null; // Set system pips (converting from half pips) status.pips_eng = pips != null ? ((decimal?)pips[1] / 2) : null; // Set engine pips (converting from half pips) status.pips_wea = pips != null ? ((decimal?)pips[2] / 2) : null; // Set weapon pips (converting from half pips) status.firegroup = JsonParsing.getOptionalInt(data, "FireGroup"); int?gui_focus = JsonParsing.getOptionalInt(data, "GuiFocus"); switch (gui_focus) { case 0: // No focus { status.gui_focus = "none"; break; } case 1: // InternalPanel (right hand side) { status.gui_focus = "internal panel"; break; } case 2: // ExternalPanel (left hand side) { status.gui_focus = "external panel"; break; } case 3: // CommsPanel (top) { status.gui_focus = "communications panel"; break; } case 4: // RolePanel (bottom) { status.gui_focus = "role panel"; break; } case 5: // StationServices { status.gui_focus = "station services"; break; } case 6: // GalaxyMap { status.gui_focus = "galaxy map"; break; } case 7: // SystemMap { status.gui_focus = "system map"; break; } case 8: // Orrery { status.gui_focus = "orrery"; break; } case 9: // FSS mode { status.gui_focus = "fss mode"; break; } case 10: // SAA mode { status.gui_focus = "saa mode"; break; } case 11: // Codex { status.gui_focus = "codex"; break; } } status.latitude = JsonParsing.getOptionalDecimal(data, "Latitude"); status.longitude = JsonParsing.getOptionalDecimal(data, "Longitude"); status.altitude = JsonParsing.getOptionalDecimal(data, "Altitude"); status.heading = JsonParsing.getOptionalDecimal(data, "Heading"); if (data.TryGetValue("Fuel", out object fuelData)) { if (fuelData is IDictionary <string, object> fuelInfo) { status.fuelInTanks = JsonParsing.getOptionalDecimal(fuelInfo, "FuelMain"); status.fuelInReservoir = JsonParsing.getOptionalDecimal(fuelInfo, "FuelReservoir"); } } status.cargo_carried = (int?)JsonParsing.getOptionalDecimal(data, "Cargo"); status.legalStatus = LegalStatus.FromEDName(JsonParsing.getString(data, "LegalState")) ?? LegalStatus.Clean; status.bodyname = JsonParsing.getString(data, "BodyName"); status.planetradius = JsonParsing.getOptionalDecimal(data, "PlanetRadius"); // Calculated data SetFuelExtras(status); SetSlope(status); return(status); } } catch (Exception ex) { Logging.Warn("Failed to parse Status.json line: " + ex.ToString()); Logging.Error("", ex); } return(null); }
public static Status ParseStatusEntry(string line) { Status status = new Status(); try { Match match = JsonRegex.Match(line); if (match.Success) { IDictionary <string, object> data = Deserializtion.DeserializeData(line); // Every status event has a timestamp field if (data.ContainsKey("timestamp")) { if (data["timestamp"] is DateTime) { status.timestamp = ((DateTime)data["timestamp"]).ToUniversalTime(); } else { status.timestamp = DateTime.Parse(JsonParsing.getString(data, "timestamp")).ToUniversalTime(); } } else { Logging.Warn("Status event without timestamp; using current time"); } status.flags = (Status.Flags)(JsonParsing.getOptionalLong(data, "Flags") ?? 0); if (status.flags == Status.Flags.None) { // No flags are set. We aren't in game. return(status); } object val; data.TryGetValue("Pips", out val); List <long> pips = ((List <object>)val)?.Cast <long>()?.ToList(); // The 'TryGetValue' function returns these values as type 'object<long>' status.pips_sys = pips != null ? ((decimal?)pips[0] / 2) : null; // Set system pips (converting from half pips) status.pips_eng = pips != null ? ((decimal?)pips[1] / 2) : null; // Set engine pips (converting from half pips) status.pips_wea = pips != null ? ((decimal?)pips[2] / 2) : null; // Set weapon pips (converting from half pips) status.firegroup = JsonParsing.getOptionalInt(data, "FireGroup"); int?gui_focus = JsonParsing.getOptionalInt(data, "GuiFocus"); switch (gui_focus) { case 0: // No focus { status.gui_focus = "none"; break; } case 1: // InternalPanel (right hand side) { status.gui_focus = "internal panel"; break; } case 2: // ExternalPanel (left hand side) { status.gui_focus = "external panel"; break; } case 3: // CommsPanel (top) { status.gui_focus = "communications panel"; break; } case 4: // RolePanel (bottom) { status.gui_focus = "role panel"; break; } case 5: // StationServices { status.gui_focus = "station services"; break; } case 6: // GalaxyMap { status.gui_focus = "galaxy map"; break; } case 7: // SystemMap { status.gui_focus = "system map"; break; } } status.latitude = JsonParsing.getOptionalDecimal(data, "Latitude"); status.longitude = JsonParsing.getOptionalDecimal(data, "Longitude"); status.altitude = JsonParsing.getOptionalDecimal(data, "Altitude"); status.heading = JsonParsing.getOptionalDecimal(data, "Heading"); return(status); } } catch (Exception ex) { Logging.Warn("Failed to parse Status.json line: " + ex.ToString()); Logging.Error(ex); } return(status = null); }
public List <StarSystem> GetStarSystems(string[] names, bool refreshIfOutdated = true) { if (!File.Exists(DbFile)) { return(null); } if (!names.Any()) { return(null); } List <StarSystem> results = new List <StarSystem>(); List <KeyValuePair <string, object> > systemsToUpdate = new List <KeyValuePair <string, object> >(); List <KeyValuePair <string, string> > dataSets = Instance.ReadStarSystems(names); bool needToUpdate = false; foreach (KeyValuePair <string, string> kv in dataSets) { if (!string.IsNullOrEmpty(kv.Value)) { string name = kv.Key; // Old versions of the data could have a string "No volcanism" for volcanism. If so we remove it string data = kv.Value?.Replace(@"""No volcanism""", "null"); // Old versions of the data could have a string "InterstellarFactorsContact" for the facilitator station service. If so we update it data = kv.Value?.Replace(@"""InterstellarFactorsContact""", @"""Facilitator"""); // Determine whether our data is stale (We won't deserialize the the entire system if it's stale) IDictionary <string, object> system = Deserializtion.DeserializeData(data); system.TryGetValue("lastupdated", out object lastUpdatedVal); system.TryGetValue("systemAddress", out object systemAddressVal); system.TryGetValue("EDSMID", out object edsmIdVal); DateTime?lastupdated = (DateTime?)lastUpdatedVal; long? systemAddress = (long?)systemAddressVal; long? edsmId = (long?)edsmIdVal; if (refreshIfOutdated) { if (lastupdated < DateTime.UtcNow.AddHours(-1)) { // Data is stale needToUpdate = true; } else if (lastupdated is null) { // We have no record of ever updating this star system needToUpdate = true; } else if (SCHEMA_VERSION >= 2 && (systemAddress is null || edsmId is null)) { // Obtain data for optimized data searches starting with schema version 2 needToUpdate = true; } } if (needToUpdate) { // We want to update this star system (don't deserialize the old result at this time) systemsToUpdate.Add(new KeyValuePair <string, object>(name, system)); } else { // Deserialize the old result StarSystem result = DeserializeStarSystem(name, data, ref needToUpdate); if (result != null) { results.Add(result); } } } } if (systemsToUpdate.Count > 0) { List <StarSystem> updatedSystems = dataProviderService.GetSystemsData(systemsToUpdate.Select(s => s.Key).ToArray()); // If the newly fetched star system is an empty object except (for the object name), reject it // Return old results when new results have been rejected List <string> systemsToRevert = new List <string>(); foreach (StarSystem starSystem in updatedSystems) { if (starSystem.systemAddress == null) { systemsToRevert.Add(starSystem.systemname); } } updatedSystems.RemoveAll(s => systemsToRevert.Contains(s.systemname)); foreach (string systemName in systemsToRevert) { results.Add(GetStarSystem(systemName, false)); } // Synchronize EDSM visits and comments updatedSystems = dataProviderService.syncFromStarMapService(updatedSystems); // Update properties that aren't synced from the server and that we want to preserve foreach (StarSystem updatedSystem in updatedSystems) { foreach (KeyValuePair <string, object> systemToUpdate in systemsToUpdate) { if (updatedSystem.systemname == systemToUpdate.Key) { Dictionary <string, object> oldStarSystem = (Dictionary <string, object>)systemToUpdate.Value; if (oldStarSystem != null) { // Carry over StarSystem properties that we want to preserve updatedSystem.totalbodies = JsonParsing.getOptionalInt(oldStarSystem, "discoverableBodies") ?? 0; // Carry over Body properties that we want to preserve (e.g. exploration data) oldStarSystem.TryGetValue("bodies", out object bodiesVal); List <Body> oldBodies = JsonConvert.DeserializeObject <List <Body> >(JsonConvert.SerializeObject(bodiesVal)); updatedSystem.PreserveBodyData(oldBodies, updatedSystem.bodies); // Carry over Faction properties that we want to preserve (e.g. reputation data) oldStarSystem.TryGetValue("factions", out object factionsVal); if (factionsVal != null) { List <Faction> oldFactions = JsonConvert.DeserializeObject <List <Faction> >(JsonConvert.SerializeObject(factionsVal)); if (oldFactions?.Count > 0) { foreach (var updatedFaction in updatedSystem.factions) { foreach (var oldFaction in oldFactions) { if (updatedFaction.name == oldFaction.name) { updatedFaction.myreputation = oldFaction.myreputation; } } } } } // No station data needs to be carried over at this time. } } } } // Update the `lastupdated` timestamps for the systems we have updated foreach (StarSystem starSystem in updatedSystems) { starSystem.lastupdated = DateTime.UtcNow; } // Add our updated systems to our results results.AddRange(updatedSystems); // Save changes to our star systems Instance.updateStarSystems(updatedSystems); } return(results); }