public void AddHackyInAtmoLoad(Vessel hackyVessel) { if (!loadingFlyingVessels.ContainsKey(hackyVessel.id)) { HackyFlyingVesselLoad hfvl = new HackyFlyingVesselLoad(); hfvl.lastUnpackTime = Client.realtimeSinceStartup; loadingFlyingVessels.Add(hackyVessel.id, hfvl); } }
private void OnGameSceneLoadRequested(GameScenes scene) { iterateVessels.Clear(); iterateVessels.AddRange(loadingFlyingVessels.Keys); foreach (Guid vesselID in iterateVessels) { HackyFlyingVesselLoad hfvl = loadingFlyingVessels[vesselID]; vesselWorker.KillVessel(hfvl.flyingVessel); } loadingFlyingVessels.Clear(); }
public void AddHackyInAtmoLoad(Vessel hackyVessel) { if (!loadingFlyingVessels.ContainsKey(hackyVessel.id)) { HackyFlyingVesselLoad hfvl = new HackyFlyingVesselLoad(); hfvl.flyingVessel = hackyVessel; hfvl.flyingVessel.vesselRanges.landed.load = hfvl.flyingVessel.vesselRanges.flying.unload - 100f; DarkLog.Debug("Default landed unload: " + hfvl.flyingVessel.vesselRanges.landed.unload); hfvl.flyingVessel.vesselRanges.landed.unload = hfvl.flyingVessel.vesselRanges.flying.unload; hfvl.lastUnpackTime = Client.realtimeSinceStartup; loadingFlyingVessels.Add(hackyVessel.id, hfvl); } }
public void AddHackyInAtmoLoad(Vessel hackyVessel) { if (!loadingFlyingVessels.ContainsKey(hackyVessel.id)) { HackyFlyingVesselLoad hfvl = new HackyFlyingVesselLoad(); hfvl.flyingVessel = hackyVessel; hfvl.flyingVessel.vesselRanges.landed.load = hfvl.flyingVessel.vesselRanges.flying.unload - 100f; DarkLog.Debug("Default landed unload: " + hfvl.flyingVessel.vesselRanges.landed.unload); hfvl.flyingVessel.vesselRanges.landed.unload = hfvl.flyingVessel.vesselRanges.flying.unload; hfvl.lastUnpackTime = Time.realtimeSinceStartup; loadingFlyingVessels.Add(hackyVessel.id, hfvl); } }
private void OnVesselUnpack(Vessel vessel) { if (loadingFlyingVessels.ContainsKey(vessel.id)) { DarkLog.Debug("Hacky load successful: Vessel is off rails"); HackyFlyingVesselLoad hfvl = loadingFlyingVessels[vessel.id]; hfvl.flyingVessel.Landed = false; hfvl.flyingVessel.Splashed = false; hfvl.flyingVessel.landedAt = string.Empty; hfvl.flyingVessel.situation = Vessel.Situations.FLYING; loadingFlyingVessels.Remove(vessel.id); } }
private void OnVesselUnpack(Vessel vessel) { if (loadingFlyingVessels.ContainsKey(vessel.id)) { DarkLog.Debug("Hacky load successful: Vessel is off rails"); HackyFlyingVesselLoad hfvl = loadingFlyingVessels[vessel.id]; hfvl.flyingVessel.Landed = false; hfvl.flyingVessel.Splashed = false; hfvl.flyingVessel.landedAt = string.Empty; hfvl.flyingVessel.situation = Vessel.Situations.FLYING; if (hfvl.lastVesselUpdate != null) { //Stop the vessel from exploding while in unpack range. hfvl.lastVesselUpdate.Apply(); } loadingFlyingVessels.Remove(vessel.id); } }
//Also called from QuickSaveLoader public void LoadVessel(ConfigNode vesselNode) { if (vesselNode != null) { //Fix crew value numbers to Kerbal Names bool kerbalsDodged = DodgeVesselCrewValues(vesselNode); //Fix the "cannot control actiongroups bug" by dodging the last used time. DodgeVesselActionGroups(vesselNode); //Can be used for debugging incoming vessel config nodes. //vesselNode.Save(Path.Combine(KSPUtil.ApplicationRootPath, Path.Combine("DMP-RX", Planetarium.GetUniversalTime() + ".txt"))); ProtoVessel currentProto = new ProtoVessel(vesselNode, HighLogic.CurrentGame); if (kerbalsDodged && (NetworkWorker.fetch.state == ClientState.STARTING) && !LockSystem.fetch.LockExists("control-" + currentProto.vesselID) && !LockSystem.fetch.LockExists("update-" + currentProto.vesselID)) { DarkLog.Debug("Sending kerbal-dodged vessel " + currentProto.vesselID + ", name: " + currentProto.vesselName); NetworkWorker.fetch.SendVesselProtoMessage(currentProto, false, false); foreach (ProtoPartSnapshot pps in currentProto.protoPartSnapshots) { if (pps.protoModuleCrew != null) { foreach (ProtoCrewMember pcm in pps.protoModuleCrew) { if (pcm != null) { NetworkWorker.fetch.SendKerbalProtoMessage(pcm); } } } } } if (currentProto != null) { //Skip already loaded EVA's if ((currentProto.vesselType == VesselType.EVA) && (FlightGlobals.fetch.vessels.Find(v => v.id == currentProto.vesselID) != null)) { return; } //Register asteroids from other players if (currentProto.vesselType == VesselType.SpaceObject) { if (currentProto.protoPartSnapshots != null) { if (currentProto.protoPartSnapshots.Count == 1) { if (currentProto.protoPartSnapshots[0].partName == "PotatoRoid") { DarkLog.Debug("Registering remote server asteroid"); AsteroidWorker.fetch.RegisterServerAsteroid(currentProto.vesselID.ToString()); } } } } //Skip vessels that try to load in the safety bubble if (isProtoVesselInSafetyBubble(currentProto)) { DarkLog.Debug("Skipped loading protovessel " + currentProto.vesselID.ToString() + ", name: " + currentProto.vesselName + " because it is inside the safety bubble"); return; } //Skip flying vessel that are too far away bool usingHackyAtmoLoad = false; if (currentProto.situation == Vessel.Situations.FLYING) { DarkLog.Debug("Got a flying update for " + currentProto.vesselID + ", name: " + currentProto.vesselName); if (currentProto.orbitSnapShot == null) { DarkLog.Debug("Skipping flying vessel load - Protovessel does not have an orbit snapshot"); return; } CelestialBody updateBody = FlightGlobals.fetch.bodies[currentProto.orbitSnapShot.ReferenceBodyIndex]; if (updateBody == null) { DarkLog.Debug("Skipping flying vessel load - Could not find celestial body index " + currentProto.orbitSnapShot.ReferenceBodyIndex); return; } bool willGetKilledInAtmo = false; if (updateBody.atmosphere) { double atmoPressure = updateBody.staticPressureASL * Math.Pow(Math.E, ((-currentProto.altitude) / (updateBody.atmosphereScaleHeight * 1000))); //KSP magic cut off limit for killing vessels. Works out to be ~23km on kerbin. if (atmoPressure > 0.01f) { willGetKilledInAtmo = true; } } if (willGetKilledInAtmo) { if (HighLogic.LoadedScene == GameScenes.FLIGHT) { if ((FlightGlobals.fetch.vessels.Find(v => v.id == currentProto.vesselID) != null) && vesselPartCount.ContainsKey(currentProto.vesselID.ToString()) ? currentProto.protoPartSnapshots.Count == vesselPartCount[currentProto.vesselID.ToString()] : false) { DarkLog.Debug("Skipping flying vessel load - Vessel has the same part count"); return; } if (FlightGlobals.fetch.activeVessel == null) { DarkLog.Debug("Skipping flying vessel load - We do not have an active vessel"); return; } if (FlightGlobals.fetch.activeVessel.mainBody != updateBody) { DarkLog.Debug("Skipping flying vessel load - We are on a different celestial body"); return; } Vector3d ourPos = FlightGlobals.fetch.activeVessel.mainBody.GetWorldSurfacePosition(FlightGlobals.fetch.activeVessel.latitude, FlightGlobals.fetch.activeVessel.longitude, FlightGlobals.fetch.activeVessel.altitude); Vector3d protoPos = updateBody.GetWorldSurfacePosition(currentProto.latitude, currentProto.longitude, currentProto.altitude); double distance = Vector3d.Distance(ourPos, protoPos); //We'll load the vessel if possible if (distance > Vessel.loadDistance) { DarkLog.Debug("Skipping flying vessel load - We are not close enough, distance: " + distance); return; } else { DarkLog.Debug("Enabling FLYING vessel load!"); //If the vessel is landed it won't be killed by the atmosphere currentProto.landed = true; usingHackyAtmoLoad = true; } } else { DarkLog.Debug("Skipping flying vessel load - We cannot load vessels that will get killed in atmosphere while not in flight"); return; } } } RegisterServerVessel(currentProto.vesselID.ToString()); DarkLog.Debug("Loading " + currentProto.vesselID + ", name: " + currentProto.vesselName + ", type: " + currentProto.vesselType); foreach (ProtoPartSnapshot part in currentProto.protoPartSnapshots) { //This line doesn't actually do anything useful, but if you get this reference, you're officially the most geeky person darklight knows. part.temperature = ((part.temperature + 273.15f) * 0.8f) - 273.15f; //Fix up flag URLS. if (part.flagURL.Length != 0) { string flagFile = Path.Combine(Path.Combine(KSPUtil.ApplicationRootPath, "GameData"), part.flagURL + ".png"); if (!File.Exists(flagFile)) { DarkLog.Debug("Flag '" + part.flagURL + "' doesn't exist, setting to default!"); part.flagURL = "Squad/Flags/default"; } } } bool wasActive = false; bool wasTarget = false; if (HighLogic.LoadedScene == GameScenes.FLIGHT) { if (FlightGlobals.fetch.VesselTarget != null ? FlightGlobals.fetch.VesselTarget.GetVessel() != null : false) { wasTarget = FlightGlobals.fetch.VesselTarget.GetVessel().id == currentProto.vesselID; } if (wasTarget) { DarkLog.Debug("ProtoVessel update for target vessel!"); } wasActive = (FlightGlobals.fetch.activeVessel != null) ? (FlightGlobals.fetch.activeVessel.id == currentProto.vesselID) : false; } for (int vesselID = FlightGlobals.fetch.vessels.Count - 1; vesselID >= 0; vesselID--) { Vessel oldVessel = FlightGlobals.fetch.vessels[vesselID]; if (oldVessel.id.ToString() == currentProto.vesselID.ToString()) { //Don't replace the vessel if it's unpacked, not landed, close to the ground, and has the same amount of parts. double hft = oldVessel.GetHeightFromTerrain(); if (oldVessel.loaded && !oldVessel.packed && !oldVessel.Landed && (hft != -1) && (hft < 1000) && (currentProto.protoPartSnapshots.Count == oldVessel.parts.Count)) { DarkLog.Debug("Skipped loading protovessel " + currentProto.vesselID.ToString() + " because it is flying close to the ground and may get destroyed"); return; } //Don't kill the active vessel - Kill it after we switch. //Killing the active vessel causes all sorts of crazy problems. if (wasActive) { delayKillVessels.Add(oldVessel); } else { /* * Sorry guys - KSP's protovessel positioning is not as accurate as it could be. * * The loading vessel needs to come off rails in order for the error to be corrected, * but taking it off rails will allow the vessel to collide with others while it's in the incorrect spot for that fixed update. * * If the vessel is the selected target, close (unpacked), and has the same number of parts, we'll skip the protovessel load. */ if (wasTarget && !oldVessel.LandedOrSplashed && oldVessel.loaded && !oldVessel.packed && (oldVessel.parts.Count == currentProto.protoPartSnapshots.Count)) { DarkLog.Debug("Skipping loading protovessel " + currentProto.vesselID.ToString() + " because it is the selected target and may crash into us"); return; } KillVessel(oldVessel); } } } vesselPartCount[currentProto.vesselID.ToString()] = currentProto.protoPartSnapshots.Count; serverVesselsProtoUpdate[currentProto.vesselID.ToString()] = UnityEngine.Time.realtimeSinceStartup; lastLoadVessel[currentProto.vesselID.ToString()] = UnityEngine.Time.realtimeSinceStartup; currentProto.Load(HighLogic.CurrentGame.flightState); if (currentProto.vesselRef != null) { if (usingHackyAtmoLoad) { //Dodge unpack/pack distances currentProto.vesselRef.distanceUnpackThreshold = Vessel.loadDistance - 300; currentProto.vesselRef.distanceLandedUnpackThreshold = Vessel.loadDistance - 300; currentProto.vesselRef.distancePackThreshold = Vessel.loadDistance - 100; currentProto.vesselRef.distanceLandedPackThreshold = Vessel.loadDistance - 100; HackyFlyingVesselLoad hfvl = new HackyFlyingVesselLoad(); hfvl.flyingVessel = currentProto.vesselRef; hfvl.loadTime = UnityEngine.Time.realtimeSinceStartup; loadingFlyingVessels.Add(hfvl); } if (wasActive) { DarkLog.Debug("ProtoVessel update for active vessel!"); try { OrbitPhysicsManager.HoldVesselUnpack(5); FlightGlobals.fetch.activeVessel.GoOnRails(); //Put our vessel on rails so we don't collide with the new copy } catch { DarkLog.Debug("WARNING: Something very bad happened trying to replace the vessel, skipping update!"); return; } newActiveVessel = currentProto.vesselRef; } if (wasTarget) { DarkLog.Debug("Set docking target"); FlightGlobals.fetch.SetVesselTarget(currentProto.vesselRef); } DarkLog.Debug("Protovessel Loaded"); } else { DarkLog.Debug("Protovessel " + currentProto.vesselID + " failed to create a vessel!"); } } else { DarkLog.Debug("protoVessel is null!"); } } else { DarkLog.Debug("vesselNode is null!"); } }
private void UpdateVessels() { iterateVessels.Clear(); iterateVessels.AddRange(loadingFlyingVessels.Keys); foreach (Guid vesselID in iterateVessels) { if (!loadingFlyingVessels.ContainsKey(vesselID)) { continue; } HackyFlyingVesselLoad hfvl = loadingFlyingVessels[vesselID]; if (hfvl.flyingVessel == null || hfvl.flyingVessel.state == Vessel.State.DEAD) { DarkLog.Debug("Hacky load failed: Vessel destroyed"); loadingFlyingVessels.Remove(vesselID); continue; } if (!FlightGlobals.fetch.vessels.Contains(hfvl.flyingVessel)) { DarkLog.Debug("Hacky load failed: Vessel destroyed"); loadingFlyingVessels.Remove(vesselID); continue; } if (!lockSystem.LockExists("update-" + vesselID) || lockSystem.LockIsOurs("update-" + vesselID)) { DarkLog.Debug("Hacky load removed: Vessel stopped being controlled by another player"); loadingFlyingVessels.Remove(vesselID); vesselWorker.KillVessel(hfvl.flyingVessel); continue; } if (hfvl.flyingVessel.loaded) { if ((Client.realtimeSinceStartup - hfvl.lastUnpackTime) > UNPACK_INTERVAL) { DarkLog.Debug("Hacky load attempting to take loaded vessel off rails"); hfvl.lastUnpackTime = Client.realtimeSinceStartup; try { hfvl.flyingVessel.GoOffRails(); } catch (Exception e) { //Just in case, I don't think this can throw but you never really know with KSP. DarkLog.Debug("Hacky load failed to take vessel of rails: " + e.Message); } continue; } } if (!hfvl.flyingVessel.packed) { DarkLog.Debug("Hacky load successful: Vessel is off rails"); loadingFlyingVessels.Remove(vesselID); hfvl.flyingVessel.Landed = false; hfvl.flyingVessel.Splashed = false; hfvl.flyingVessel.landedAt = string.Empty; hfvl.flyingVessel.situation = Vessel.Situations.FLYING; hfvl.flyingVessel.vesselRanges.landed.load = LANDED_LOAD_DISTANCE_DEFAULT; hfvl.flyingVessel.vesselRanges.landed.unload = LANDED_UNLOAD_DISTANCE_DEFAULT; continue; } double atmoPressure = hfvl.flyingVessel.mainBody.GetPressure(hfvl.flyingVessel.altitude); if (atmoPressure < 0.01d) { DarkLog.Debug("Hacky load successful: Vessel is now safe from atmo"); loadingFlyingVessels.Remove(vesselID); hfvl.flyingVessel.Landed = false; hfvl.flyingVessel.Splashed = false; hfvl.flyingVessel.landedAt = string.Empty; hfvl.flyingVessel.situation = Vessel.Situations.FLYING; hfvl.flyingVessel.vesselRanges.landed.load = LANDED_LOAD_DISTANCE_DEFAULT; hfvl.flyingVessel.vesselRanges.landed.unload = LANDED_UNLOAD_DISTANCE_DEFAULT; continue; } if (hfvl.lastVesselUpdate != null) { hfvl.lastVesselUpdate.Apply(); } } }