DeepFreeze Continued...

DeepFreeze Continued...

38.2k Downloads

DF.DeepFreezer.OnDestroy throwing NullReferenceExceptions in KSP 1.12.3

AmanitaVerna opened this issue · 5 comments

commented

I'm seeing NullReferenceExceptions in the logs for the freezer objects, coming from DF.DeepFreezer.OnDestroy, when PartLoader is compiling stuff and making drag cubes. It's happening with both the CRY5000 provided by Kerbal Planetary Base Systems, and with the other CRY models provided by DeepFreeze itself.

In KSP.log, they look like this:

[LOG 12:42:43.052] PartLoader: Compiling Part 'PlanetaryBaseInc/ModSupport/Parts/DeepFreeze/Cryo5000Freezer/Cryo5000Freezer/CRY-5000Freezer'
[WRN 12:42:43.064] [Part]: Cannot add ModuleCargoPart as this Part 'CRY-5000Freezer' already has a ModuleInventoryPart PartModule and they are mutually exclusive.
[LOG 12:42:43.070] DeepFreezer OnDestroy
[EXC 12:42:43.071] NullReferenceException: Object reference not set to an instance of an object
DF.DeepFreezer.OnDestroy () (at <72233efaa3ee4936a15201f98fac7b68>:0)
UnityEngine.DebugLogHandler:LogException(Exception, Object)
ModuleManager.UnityLogHandle.InterceptLogHandler:LogException(Exception, Object)
UnityEngine.Object:DestroyImmediate(Object)
PartLoader:StripComponent(GameObject)
PartLoader:CreatePartIcon(GameObject, Single&)
PartLoader:ParsePart(UrlConfig, ConfigNode)
d__56:MoveNext()
UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)
[LOG 12:42:43.074] PartLoader: Part 'PlanetaryBaseInc/ModSupport/Parts/DeepFreeze/Cryo5000Freezer/Cryo5000Freezer/CRY-5000Freezer' has no database record. Creating.
[LOG 12:42:43.074] [DragCubeSystem]: Drag cubes not found or cannot be read for part Part. Generating New drag cubes.
[LOG 12:42:43.079] DragCubeSystem: Creating drag cubes for part 'CRY-5000Freezer'
[LOG 12:42:43.102] DeepFreezer OnDestroy
[EXC 12:42:43.103] NullReferenceException: Object reference not set to an instance of an object
DF.DeepFreezer.OnDestroy () (at <72233efaa3ee4936a15201f98fac7b68>:0)
UnityEngine.DebugLogHandler:LogException(Exception, Object)
ModuleManager.UnityLogHandle.InterceptLogHandler:LogException(Exception, Object)
UnityEngine.Object:DestroyImmediate(Object)
d__34:MoveNext()
UnityEngine.SetupCoroutine:InvokeMoveNext(IEnumerator, IntPtr)

I tried removing KSP_PartVolume, but I still got the exceptions in the logs without it, so it doesn't appear to be related.

KSP.log
Player.log

commented

yeah, it was reported on net-lisias-ksp/KSP-Recall#40 too.

I want to stress out that this was working perfectly fine on KSP 1.9.1, so it's something that changed on KSP itself for sure. Since this started to happen recently, I'm guessing that whatever changed on KSP, did it on 1.12.0.

My best guess is that the problem is happening on this code:

protected void OnDestroy()

        protected void OnDestroy()
        {
            Utilities.Log("OnDestroy");
            Instance = null;
            APIReady = false;
            foreach (Component child in children)
            {
                Utilities.Log("DeepFreeze Child Destroy for " + child.name);
                Destroy(child);
            }
            children.Clear();
            DeepFreezeEventRem();
            GameEvents.onGameSceneLoadRequested.Remove(OnGameSceneLoadRequested);
            GameEvents.OnGameSettingsApplied.Remove(ApplySettings);
        }

EDIT: NOPE!! I was fooled by a (unhappy) log message.

commented

KSP is not at fault here. This is what was really happening.

The DeepFreezePart.OnDestroy (the PartModule) was the code borking, not the DeepFreeze.OnDestroy (the Scenario Module).

That log message completely misguided me. The real problem is on this code:

private void OnDestroy()

        private void OnDestroy()
        {
            //Remove GameEvent callbacks.
            Debug.Log("DeepFreezer OnDestroy");
            
                GameEvents.onCrewTransferPartListCreated.Remove(onCrewTransferPartListCreated);
                GameEvents.onCrewTransferred.Remove(onCrewTransferred);
                GameEvents.onVesselChange.Remove(OnVesselChange);
                GameEvents.onCrewBoardVessel.Remove(OnCrewBoardVessel);
                GameEvents.onCrewOnEva.Remove(onCrewOnEva);
                GameEvents.onVesselDestroy.Remove(onVesselDestroy);
                GameEvents.OnCameraChange.Remove(OnCameraChange);
                GameEvents.onVesselGoOffRails.Remove(onVesselGoOffRails);
                GameEvents.onVesselCrewWasModified.Remove(OnVesselCrewModified);
                DFGameEvents.onKerbalFrozen.Remove(OnKerbalFreezeThaw);     // <— HERE!!!
                DFGameEvents.onKerbalThaw.Remove(OnKerbalFreezeThaw);
                GameEvents.onVesselSwitching.Remove(OnVesselSwitching);
                if (onATPPodSettingChanged != null)
                {
                    onATPPodSettingChanged.Remove(OnATPPodSettingChanged);
                }
            
            Debug.Log("DeepFreezer END OnDestroy");
        }

The DGGameEvents structure os initialised only on the class Textures (whatahell??) on the Start method, here:

public void Start()

Problem. Besides Textures being completely unrelated to the DFGameEvents, the Texture MonoBehaviour is started only on the Main Menu : [KSPAddon(KSPAddon.Startup.MainMenu, false)]. So it's not a surprise that the DeepFreezePart's OnDestroy is borking, as the DFGameEvents are all still NULL at that point!

The easiest way out of this huge mess is to initialise DFGameEvents on the class loading, guaranteeing that the data structures will be immediately available for using.

The big question is not why DF started to throw exceptions now, but why it wasn't doing it before.

commented

A pull request was issued fixing the issue.

#110

commented

Will be fixed in next release. Hopefully I can get that done this coming week.

commented

@JPLRepo
Good day sir! Recently I ran into a similar problem and the mod crashed a game for me.
Do you have any spare time to release an updated build with those fixes?