public List <UIEvent> Scan() { // System.Diagnostics.Debug.WriteLine(Environment.TickCount % 100000 + "Check " + statusfile); if (File.Exists(statusfile)) { JObject jo = null; Stream stream = null; try { stream = File.Open(statusfile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); StreamReader reader = new StreamReader(stream); string text = reader.ReadToEnd(); stream.Close(); if (text.HasChars() && (prev_text == null || !text.Equals(prev_text))) // if text not null, and prev text is null OR not equal { jo = JObject.ParseThrowCommaEOL(text); // and of course the json could be crap prev_text = text; // set after successful parse } } catch { } finally { if (stream != null) { stream.Dispose(); } } if (jo != null) { DateTime EventTimeUTC = jo["timestamp"].DateTimeUTC(); List <UIEvent> events = new List <UIEvent>(); UIMode shiptype = ShipType(prev_flags, prev_flags2); long curflags = jo["Flags"].Long(0); long curflags2 = jo["Flags2"].Long(0); // 0 is backwards compat with horizons bool fireoverall = false; // fire the overall bool changedmajormode = false; long flagsdelta2 = 0; // what changed between prev and current if (curflags != prev_flags || curflags2 != prev_flags2) { UIMode nextshiptype = ShipType(curflags, curflags2); //System.Diagnostics.Debug.WriteLine("UI Flags changed {0} {1} {2} -> {3} {4} {5}", prev_flags.Value, prev_flags2.Value, shiptype, curflags, curflags2, nextshiptype); if (nextshiptype.Mode != shiptype.Mode) // changed ship situation.. { changedmajormode = nextshiptype.MajorMode != shiptype.MajorMode; // did we change major mode events.Add(new UIEvents.UIMode(nextshiptype.Mode, nextshiptype.MajorMode, EventTimeUTC, changedmajormode)); // Generate an event for it } events.AddRange(ReportFlagState(typeof(StatusFlags2), curflags2, prev_flags2, EventTimeUTC, changedmajormode)); events.AddRange(ReportFlagState(typeof(StatusFlagsShip), curflags, prev_flags, EventTimeUTC, changedmajormode)); events.AddRange(ReportFlagState(typeof(StatusFlagsSRV), curflags, prev_flags, EventTimeUTC, changedmajormode)); events.AddRange(ReportFlagState(typeof(StatusFlagsAll), curflags, prev_flags, EventTimeUTC, changedmajormode)); fireoverall = true; flagsdelta2 = curflags2 ^ prev_flags2; // record the delta here for later processing, some of those flags go into the main reports prev_flags = curflags; prev_flags2 = curflags2; shiptype = nextshiptype; } int curguifocus = jo["GuiFocus"].Int(NotPresent); if (curguifocus != prev_guifocus || changedmajormode) { events.Add(new UIEvents.UIGUIFocus(curguifocus, EventTimeUTC, changedmajormode)); prev_guifocus = curguifocus; fireoverall = true; } int[] pips = jo["Pips"]?.ToObjectQ <int[]>(); // may appear/disappear UIEvents.UIPips.Pips curpips = new UIEvents.UIPips.Pips(pips); // can accept null as input if (!curpips.Equal(prev_pips) || changedmajormode) // if change in pips, or changed mode { events.Add(new UIEvents.UIPips(curpips, EventTimeUTC, changedmajormode)); prev_pips = curpips; fireoverall = true; } int curfiregroup = jo["FireGroup"].Int(NotPresent); // may appear/disappear. if (curfiregroup != prev_firegroup || changedmajormode) { events.Add(new UIEvents.UIFireGroup(curfiregroup + 1, EventTimeUTC, changedmajormode)); prev_firegroup = curfiregroup; fireoverall = true; } JToken jfuel = jo["Fuel"]; double curfuel = jfuel != null ? jfuel["FuelMain"].Double(-1) : -1; double curres = jfuel != null ? jfuel["FuelReservoir"].Double(-1) : -1; if (Math.Abs(curfuel - prev_curfuel) >= 0.1 || Math.Abs(curres - prev_curres) >= 0.01 || changedmajormode) // don't fire if small changes { events.Add(new UIEvents.UIFuel(curfuel, curres, shiptype.Mode, EventTimeUTC, changedmajormode)); prev_curfuel = curfuel; prev_curres = curres; fireoverall = true; } int curcargo = jo["Cargo"].Int(NotPresent); // may appear/disappear and only introduced for 3.3 if (curcargo != prev_cargo || changedmajormode) { events.Add(new UIEvents.UICargo(curcargo, shiptype.Mode, EventTimeUTC, changedmajormode)); prev_cargo = curcargo; fireoverall = true; } double jlat = jo["Latitude"].Double(UIEvents.UIPosition.InvalidValue); // if not there, min value double jlon = jo["Longitude"].Double(UIEvents.UIPosition.InvalidValue); double jalt = jo["Altitude"].Double(UIEvents.UIPosition.InvalidValue); double jheading = jo["Heading"].Double(UIEvents.UIPosition.InvalidValue); double jpradius = jo["PlanetRadius"].Double(UIEvents.UIPosition.InvalidValue); // 3.4 if (jlat != prev_pos.Latitude || jlon != prev_pos.Longitude || jalt != prev_pos.Altitude || jheading != prev_heading || jpradius != prev_jpradius || changedmajormode) { UIEvents.UIPosition.Position newpos = new UIEvents.UIPosition.Position() { Latitude = jlat, Longitude = jlon, Altitude = jalt, AltitudeFromAverageRadius = Flags(curflags, StatusFlagsReportedInOtherEvents.AltitudeFromAverageRadius) }; events.Add(new UIEvents.UIPosition(newpos, jheading, jpradius, EventTimeUTC, changedmajormode)); prev_pos = newpos; prev_heading = jheading; prev_jpradius = jpradius; fireoverall = true; } string cur_legalstatus = jo["LegalState"].StrNull(); if (cur_legalstatus != prev_legalstatus || changedmajormode) { events.Add(new UIEvents.UILegalStatus(cur_legalstatus, EventTimeUTC, changedmajormode)); prev_legalstatus = cur_legalstatus; fireoverall = true; } string cur_bodyname = jo["BodyName"].StrNull(); if (cur_bodyname != prev_bodyname || changedmajormode) { events.Add(new UIEvents.UIBodyName(cur_bodyname, EventTimeUTC, changedmajormode)); prev_bodyname = cur_bodyname; fireoverall = true; } string cur_weapon = jo["SelectedWeapon"].StrNull(); // null if not there string cur_weaponloc = jo["SelectedWeapon_Localised"].Str(); // empty if not there if (cur_weapon != prev_selectedweapon || changedmajormode) { events.Add(new UIEvents.UISelectedWeapon(cur_weapon, cur_weaponloc, EventTimeUTC, changedmajormode)); prev_selectedweapon = cur_weapon; prev_selectedweaponloc = cur_weaponloc; fireoverall = true; } double oxygen = jo["Oxygen"].Double(NotPresent); //-1 is not present oxygen = oxygen < 0 ? oxygen : oxygen * 100; // correct to 0-100% bool lowoxygen = Flags(curflags2, StatusFlags2OtherFlags.LowOxygen); if (oxygen != prev_oxygen || Flags(flagsdelta2, StatusFlags2OtherFlags.LowOxygen) || changedmajormode) { events.Add(new UIEvents.UIOxygen(oxygen, lowoxygen, EventTimeUTC, changedmajormode)); prev_oxygen = oxygen; fireoverall = true; } double health = jo["Health"].Double(NotPresent); //-1 is not present health = health < 0 ? health : health * 100; // correct to 0-100% bool lowhealth = Flags(curflags2, StatusFlags2OtherFlags.LowHealth); if (health != prev_health || Flags(flagsdelta2, StatusFlags2OtherFlags.LowHealth) || changedmajormode) { events.Add(new UIEvents.UIHealth(health, lowhealth, EventTimeUTC, changedmajormode)); prev_health = health; fireoverall = true; } double gravity = jo["Gravity"].Double(NotPresent); //-1 is not present if (gravity != prev_gravity || changedmajormode) { events.Add(new UIEvents.UIGravity(gravity, EventTimeUTC, changedmajormode)); prev_gravity = gravity; fireoverall = true; } double temperature = jo["Temperature"].Double(NotPresent); //-1 is not present UIEvents.UITemperature.TempState tempstate = Flags(curflags2, StatusFlags2OtherFlags.VeryCold) ? UIEvents.UITemperature.TempState.VeryCold : // order important, you can get Cold | VeryCold Flags(curflags2, StatusFlags2OtherFlags.VeryHot) ? UIEvents.UITemperature.TempState.VeryHot : Flags(curflags2, StatusFlags2OtherFlags.Cold) ? UIEvents.UITemperature.TempState.Cold : Flags(curflags2, StatusFlags2OtherFlags.Hot) ? UIEvents.UITemperature.TempState.Hot : UIEvents.UITemperature.TempState.Normal; if (temperature != prev_temperature || (flagsdelta2 & (long)StatusFlags2OtherFlags.TempBits) != 0 || changedmajormode) { events.Add(new UIEvents.UITemperature(temperature, tempstate, EventTimeUTC, changedmajormode)); prev_temperature = temperature; fireoverall = true; } if (fireoverall) { List <UITypeEnum> flagsset = ReportFlagState(typeof(StatusFlagsShip), curflags); flagsset.AddRange(ReportFlagState(typeof(StatusFlagsSRV), curflags)); flagsset.AddRange(ReportFlagState(typeof(StatusFlagsAll), curflags)); flagsset.AddRange(ReportFlagState(typeof(StatusFlags2), curflags2)); bool glidemode = Flags(curflags2, StatusFlags2.GlideMode); bool breathableatmos = Flags(curflags2, StatusFlags2.BreathableAtmosphere); UIEvents.UIOverallStatus.FSDStateType fsdstate = UIEvents.UIOverallStatus.FSDStateType.Normal; if (Flags(curflags, StatusFlagsShip.FsdMassLocked)) { fsdstate = UIEvents.UIOverallStatus.FSDStateType.MassLock; } if (Flags(curflags, StatusFlagsShip.FsdJump)) { fsdstate = UIEvents.UIOverallStatus.FSDStateType.Jumping; } else if (Flags(curflags, StatusFlagsShip.FsdCharging)) { fsdstate = UIEvents.UIOverallStatus.FSDStateType.Charging; } else if (Flags(curflags2, StatusFlags2.GlideMode)) { fsdstate = UIEvents.UIOverallStatus.FSDStateType.Gliding; } else if (Flags(curflags, StatusFlagsShip.FsdCooldown)) { fsdstate = UIEvents.UIOverallStatus.FSDStateType.Cooldown; } events.Add(new UIEvents.UIOverallStatus(shiptype.MajorMode, shiptype.Mode, flagsset, prev_guifocus, prev_pips, prev_firegroup, prev_curfuel, prev_curres, prev_cargo, prev_pos, prev_heading, prev_jpradius, prev_legalstatus, prev_bodyname, prev_health, lowhealth, gravity, prev_temperature, tempstate, prev_oxygen, lowoxygen, prev_selectedweapon, prev_selectedweaponloc, fsdstate, breathableatmos, EventTimeUTC, changedmajormode)); // overall list of flags set } //for debugging, keep #if false foreach (var uient in events) { System.Diagnostics.Trace.WriteLine(string.Format("New UI entry from journal {0} {1} refresh {2}", uient.EventTimeUTC, uient.EventTypeStr, changedmajormode)); //BaseUtils.Variables v = new BaseUtils.Variables(); //v.AddPropertiesFieldsOfClass(uient, "", null, 2); //foreach (var x in v.NameEnumuerable) // System.Diagnostics.Trace.WriteLine(string.Format(" {0} = {1}", x, v[x])); } #endif return(events); } } return(new List <UIEvent>()); }
public List <UIEvent> Scan() { // System.Diagnostics.Debug.WriteLine(Environment.TickCount % 100000 + "Check " + statusfile); if (File.Exists(statusfile)) { JObject jo = null; Stream stream = null; try { stream = File.Open(statusfile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); StreamReader reader = new StreamReader(stream); string text = reader.ReadToEnd(); stream.Close(); if (text != null && (prev_text == null || !text.Equals(prev_text))) // if text not null, and prev text is null OR not equal { jo = JObject.ParseThrowCommaEOL(text); // and of course the json could be crap prev_text = text; // set after successful parse } } catch { } finally { if (stream != null) { stream.Dispose(); } } if (jo != null) { DateTime EventTimeUTC = jo["timestamp"].DateTimeUTC(); List <UIEvent> events = new List <UIEvent>(); if (prev_flags == null) // if first run, set prev flags to impossible type. { prev_flags = (long)StatusFlagsShipType.ShipMask; // set an impossible ship type to start the ball rolling prev_flags2 = 0; } UIEvents.UIShipType.Shiptype shiptype = ShipType(prev_flags.Value, prev_flags2.Value); long curflags = jo["Flags"].Long(); long curflags2 = jo["Flags2"].Long(0); // 0 is backwards compat with horizons bool fireoverall = false; bool fireoverallrefresh = prev_guifocus == NotPresent; //meaning its a refresh long flagsdelta2 = 0; // what changed between prev and current if (curflags != prev_flags.Value || curflags2 != prev_flags2.Value) { UIEvents.UIShipType.Shiptype nextshiptype = ShipType(curflags, curflags2); //System.Diagnostics.Debug.WriteLine("UI Flags changed {0} {1} {2} -> {3} {4} {5}", prev_flags.Value, prev_flags2.Value, shiptype, curflags, curflags2, nextshiptype); bool refresh = shiptype == UIEvents.UIShipType.Shiptype.None; // refresh if prev ship was none.. if (shiptype != nextshiptype) { events.Add(new UIEvents.UIShipType(nextshiptype, EventTimeUTC, refresh)); // CHANGE of ship/on foot/taxi etc //prev_flags = ~curflags; // force re-reporting (don't think its ness) //prev_flags2 = ~curflags2; refresh = true; } if (nextshiptype != UIEvents.UIShipType.Shiptype.None) { events.AddRange(ReportFlagState(typeof(StatusFlags2), curflags2, prev_flags2.Value, EventTimeUTC, refresh)); events.AddRange(ReportFlagState(typeof(StatusFlagsShip), curflags, prev_flags.Value, EventTimeUTC, refresh)); events.AddRange(ReportFlagState(typeof(StatusFlagsSRV), curflags, prev_flags.Value, EventTimeUTC, refresh)); events.AddRange(ReportFlagState(typeof(StatusFlagsAll), curflags, prev_flags.Value, EventTimeUTC, refresh)); } flagsdelta2 = curflags2 ^ prev_flags2.Value; // record the delta here for later processing, some of those flags go into the main reports prev_flags = curflags; prev_flags2 = curflags2; shiptype = nextshiptype; fireoverall = true; } int curguifocus = jo["GuiFocus"].Int(NotPresent); if (curguifocus != prev_guifocus) { events.Add(new UIEvents.UIGUIFocus(curguifocus, EventTimeUTC, prev_guifocus == NotPresent)); prev_guifocus = curguifocus; fireoverall = true; } int[] pips = jo["Pips"]?.ToObjectQ <int[]>(); if (pips != null) { double sys = pips[0] / 2.0; // convert to normal, instead of half pips double eng = pips[1] / 2.0; double wep = pips[2] / 2.0; if (sys != prev_pips.Systems || wep != prev_pips.Weapons || eng != prev_pips.Engines) { UIEvents.UIPips.Pips newpips = new UIEvents.UIPips.Pips() { Systems = sys, Engines = eng, Weapons = wep }; events.Add(new UIEvents.UIPips(newpips, EventTimeUTC, prev_pips.Engines < 0)); prev_pips = newpips; fireoverall = true; } } else if (prev_pips.Valid) // missing pips, if we are valid.. need to clear them { UIEvents.UIPips.Pips newpips = new UIEvents.UIPips.Pips(); events.Add(new UIEvents.UIPips(newpips, EventTimeUTC, prev_pips.Engines < 0)); prev_pips = newpips; fireoverall = true; } int?curfiregroup = jo["FireGroup"].IntNull(); // may appear/disappear. if (curfiregroup != null && curfiregroup != prev_firegroup) { events.Add(new UIEvents.UIFireGroup(curfiregroup.Value + 1, EventTimeUTC, prev_firegroup == NotPresent)); prev_firegroup = curfiregroup.Value; fireoverall = true; } JToken jfuel = jo["Fuel"]; if (jfuel != null && jfuel.IsObject) // because they changed its type in 3.3.2 { double?curfuel = jfuel["FuelMain"].DoubleNull(); double?curres = jfuel["FuelReservoir"].DoubleNull(); if (curfuel != null && curres != null) { if (Math.Abs(curfuel.Value - prev_curfuel) >= 0.1 || Math.Abs(curres.Value - prev_curres) >= 0.01) // don't fire if small changes { //System.Diagnostics.Debug.WriteLine("UIEvent Fuel " + curfuel.Value + " " + prev_curfuel + " Res " + curres.Value + " " + prev_curres); events.Add(new UIEvents.UIFuel(curfuel.Value, curres.Value, shiptype, EventTimeUTC, prev_firegroup == NotPresent)); prev_curfuel = curfuel.Value; prev_curres = curres.Value; fireoverall = true; } } } int?curcargo = jo["Cargo"].IntNull(); // may appear/disappear and only introduced for 3.3 if (curcargo != null && curcargo.Value != prev_cargo) { events.Add(new UIEvents.UICargo(curcargo.Value, shiptype, EventTimeUTC, prev_firegroup == NotPresent)); prev_cargo = curcargo.Value; fireoverall = true; } double jlat = jo["Latitude"].Double(UIEvents.UIPosition.InvalidValue); // if not there, min value double jlon = jo["Longitude"].Double(UIEvents.UIPosition.InvalidValue); double jalt = jo["Altitude"].Double(UIEvents.UIPosition.InvalidValue); double jheading = jo["Heading"].Double(UIEvents.UIPosition.InvalidValue); double jpradius = jo["PlanetRadius"].Double(UIEvents.UIPosition.InvalidValue); // 3.4 if (jlat != prev_pos.Latitude || jlon != prev_pos.Longitude || jalt != prev_pos.Altitude || jheading != prev_heading || jpradius != prev_jpradius) { UIEvents.UIPosition.Position newpos = new UIEvents.UIPosition.Position() { Latitude = jlat, Longitude = jlon, Altitude = jalt, AltitudeFromAverageRadius = Flags(curflags, StatusFlagsReportedInOtherEvents.AltitudeFromAverageRadius) }; events.Add(new UIEvents.UIPosition(newpos, jheading, jpradius, EventTimeUTC, prev_pos.ValidPosition == false)); prev_pos = newpos; prev_heading = jheading; prev_jpradius = jpradius; fireoverall = true; } string cur_legalstatus = jo["LegalState"].StrNull(); if (cur_legalstatus != prev_legalstatus) { events.Add(new UIEvents.UILegalStatus(cur_legalstatus, EventTimeUTC, prev_legalstatus == null)); prev_legalstatus = cur_legalstatus; fireoverall = true; } string cur_bodyname = jo["BodyName"].StrNull(); if (cur_bodyname != prev_bodyname) { events.Add(new UIEvents.UIBodyName(cur_bodyname, EventTimeUTC, prev_bodyname == null)); prev_bodyname = cur_bodyname; fireoverall = true; } string cur_weapon = jo["SelectedWeapon"].StrNull(); // null if not there string cur_weaponloc = jo["SelectedWeapon_Localised"].Str(); // empty if not there if (cur_weapon != prev_selectedweapon) { events.Add(new UIEvents.UISelectedWeapon(cur_weapon, cur_weaponloc, EventTimeUTC, prev_selectedweapon == null)); prev_selectedweapon = cur_weapon; prev_selectedweaponloc = cur_weaponloc; fireoverall = true; } double oxygen = jo["Oxygen"].Double(NotPresent); //-1 is not present oxygen = oxygen < 0 ? oxygen : oxygen * 100; // correct to 0-100% bool lowoxygen = Flags(curflags2, StatusFlags2OtherFlags.LowOxygen); if (oxygen != prev_oxygen || Flags(flagsdelta2, StatusFlags2OtherFlags.LowOxygen)) { events.Add(new UIEvents.UIOxygen(oxygen, lowoxygen, EventTimeUTC, prev_oxygen < 0)); prev_oxygen = oxygen; fireoverall = true; } double health = jo["Health"].Double(NotPresent); //-1 is not present health = health < 0 ? health : health * 100; // correct to 0-100% bool lowhealth = Flags(curflags2, StatusFlags2OtherFlags.LowHealth); if (health != prev_health || Flags(flagsdelta2, StatusFlags2OtherFlags.LowHealth)) { events.Add(new UIEvents.UIHealth(health, lowhealth, EventTimeUTC, prev_health < 0)); prev_health = health; fireoverall = true; } double gravity = jo["Gravity"].Double(NotPresent); //-1 is not present if (gravity != prev_gravity) { events.Add(new UIEvents.UIGravity(gravity, EventTimeUTC, prev_gravity < 0)); prev_gravity = gravity; fireoverall = true; } double temperature = jo["Temperature"].Double(NotPresent); //-1 is not present UIEvents.UITemperature.TempState tempstate = Flags(curflags2, StatusFlags2OtherFlags.VeryCold) ? UIEvents.UITemperature.TempState.VeryCold : // order important, you can get Cold | VeryCold Flags(curflags2, StatusFlags2OtherFlags.VeryHot) ? UIEvents.UITemperature.TempState.VeryHot : Flags(curflags2, StatusFlags2OtherFlags.Cold) ? UIEvents.UITemperature.TempState.Cold : Flags(curflags2, StatusFlags2OtherFlags.Hot) ? UIEvents.UITemperature.TempState.Hot : UIEvents.UITemperature.TempState.Normal; if (temperature != prev_temperature || (flagsdelta2 & (long)StatusFlags2OtherFlags.TempBits) != 0) { events.Add(new UIEvents.UITemperature(temperature, tempstate, EventTimeUTC, prev_temperature < 0)); prev_temperature = temperature; fireoverall = true; } if (fireoverall) { List <UITypeEnum> flagsset = ReportFlagState(typeof(StatusFlagsShip), curflags); flagsset.AddRange(ReportFlagState(typeof(StatusFlagsSRV), curflags)); flagsset.AddRange(ReportFlagState(typeof(StatusFlagsAll), curflags)); flagsset.AddRange(ReportFlagState(typeof(StatusFlags2), curflags2)); bool glidemode = Flags(curflags2, StatusFlags2.GlideMode); bool breathableatmos = Flags(curflags2, StatusFlags2.BreathableAtmosphere); UIEvents.UIOverallStatus.FSDStateType fsdstate = UIEvents.UIOverallStatus.FSDStateType.Normal; if (Flags(curflags, StatusFlagsShip.FsdJump)) { fsdstate = UIEvents.UIOverallStatus.FSDStateType.Jumping; } else if (Flags(curflags, StatusFlagsShip.FsdCharging)) { fsdstate = UIEvents.UIOverallStatus.FSDStateType.Charging; } else if (Flags(curflags2, StatusFlags2.GlideMode)) { fsdstate = UIEvents.UIOverallStatus.FSDStateType.Gliding; } else if (Flags(curflags, StatusFlagsShip.FsdCooldown)) { fsdstate = UIEvents.UIOverallStatus.FSDStateType.Cooldown; } events.Add(new UIEvents.UIOverallStatus(shiptype, flagsset, prev_guifocus, prev_pips, prev_firegroup, prev_curfuel, prev_curres, prev_cargo, prev_pos, prev_heading, prev_jpradius, prev_legalstatus, prev_bodyname, prev_health, lowhealth, gravity, prev_temperature, tempstate, prev_oxygen, lowoxygen, prev_selectedweapon, prev_selectedweaponloc, fsdstate, breathableatmos, EventTimeUTC, fireoverallrefresh)); // overall list of flags set } //for debugging, keep #if false foreach (var uient in events) { BaseUtils.Variables v = new BaseUtils.Variables(); v.AddPropertiesFieldsOfClass(uient, "", null, 2); System.Diagnostics.Trace.WriteLine(string.Format("New UI entry from journal {0} {1}", uient.EventTimeUTC, uient.EventTypeStr)); foreach (var x in v.NameEnumuerable) { System.Diagnostics.Trace.WriteLine(string.Format(" {0} = {1}", x, v[x])); } } #endif return(events); } } return(new List <UIEvent>()); }