/// <summary>
        /// GameEvent of any deployed science part changed in state
        /// </summary>
        protected void groundSciencePartStateChange(ModuleGroundSciencePart sciencePart)
        {
            if (sciencePart is ModuleGroundExpControl)
            {
                //toggle antenna module based on part enabled toggling
                Part controlStation = sciencePart.part;
                CNConstellationAntennaModule antennaMod = controlStation.FindModuleImplementing <CNConstellationAntennaModule>();
                if (antennaMod != null)
                {
                    antennaMod.InUse = sciencePart.Enabled;
                    //Comment: Control Station has CanComm=false at this point -> require player action
                }

                this.rebuildFreqList(true);
            }
            else if (sciencePart is ModuleGroundCommsPart)
            {
                this.rebuildFreqList(true);
            }
        }
        /// <summary>
        /// Check if given vessel has CNConstellationModule and its attributes required, and if not, "upgrade" the vessel data
        /// </summary>
        public void validateAndUpgrade(Vessel thisVessel)
        {
            if (thisVessel == null)
            {
                return;
            }
            if (thisVessel.loaded) // it seems KSP will automatically add/upgrade the active vessel (unconfirmed)
            {
                return;
            }

            CNCLog.Debug("Unloaded CommNet vessel '{0}' is validated and upgraded", thisVessel.GetName());

            if (thisVessel.protoVessel != null)
            {
                List <ProtoPartSnapshot> parts = thisVessel.protoVessel.protoPartSnapshots;
                for (int i = 0; i < parts.Count; i++)
                {
                    if (parts[i].FindModule("ModuleCommand") != null) // check command parts only
                    {
                        ProtoPartModuleSnapshot cncModule;
                        if ((cncModule = parts[i].FindModule("CNConstellationModule")) == null)                      //check if CNConstellationModule is there
                        {
                            CNConstellationModule realcncModule = gameObject.AddComponent <CNConstellationModule>(); // don't use new keyword. PartModule is Monobehavior
                            parts[i].modules.Add(new ProtoPartModuleSnapshot(realcncModule));

                            CNCLog.Verbose("CNConstellationModule is added to CommNet Vessel '{0}'", thisVessel.GetName());
                        }
                        else //check if all attributes are or should not be there
                        {
                            if (cncModule.moduleValues.HasValue("radioFrequency")) //obsolete
                            {
                                cncModule.moduleValues.RemoveValue("radioFrequency");
                            }

                            if (cncModule.moduleValues.HasValue("communicationMembershipFlag")) //obsolete
                            {
                                cncModule.moduleValues.RemoveValue("communicationMembershipFlag");
                            }
                        }
                    }

                    if (parts[i].FindModule("ModuleDataTransmitter") != null) // check antennas, probe cores and manned cockpits
                    {
                        ProtoPartModuleSnapshot cncModule;
                        if ((cncModule = parts[i].FindModule("CNConstellationAntennaModule")) == null)                             //check if CNConstellationAntennaModule is there
                        {
                            CNConstellationAntennaModule realcncModule = gameObject.AddComponent <CNConstellationAntennaModule>(); // don't use new keyword. PartModule is Monobehavior
                            parts[i].modules.Add(new ProtoPartModuleSnapshot(realcncModule));

                            CNCLog.Verbose("CNConstellationAntennaModule is added to CommNet Vessel '{0}'", thisVessel.GetName());
                        }
                        else //check if all attributes are or should not be there
                        {
                            if (!cncModule.moduleValues.HasValue("CosAngle"))
                            {
                                cncModule.moduleValues.AddValue("CosAngle", -1.0);
                            }
                        }
                    }
                } // end of part loop
            }
        }
        /// <summary>
        /// Read the part data of an unloaded/loaded vessel and store in data structures
        /// </summary>
        protected List <CNCAntennaPartInfo> readAntennaData()
        {
            List <CNCAntennaPartInfo> antennas = new List <CNCAntennaPartInfo>();
            int numParts = (!this.vessel.loaded) ? this.vessel.protoVessel.protoPartSnapshots.Count : this.vessel.Parts.Count;

            //inspect each part
            for (int partIndex = 0; partIndex < numParts; partIndex++)
            {
                Part thisPart;
                ProtoPartSnapshot partSnapshot = null;

                if (this.Vessel.loaded)
                {
                    thisPart = this.vessel.Parts[partIndex];
                }
                else
                {
                    partSnapshot = this.vessel.protoVessel.protoPartSnapshots[partIndex];
                    thisPart     = partSnapshot.partInfo.partPrefab;
                }

                bool populatedAntennaInfo = false;
                CNCAntennaPartInfo      newAntennaPartInfo = new CNCAntennaPartInfo();;
                ProtoPartModuleSnapshot partModuleSnapshot = null;

                //inspect each module of the part
                for (int moduleIndex = 0; moduleIndex < thisPart.Modules.Count; moduleIndex++)
                {
                    PartModule thisPartModule = thisPart.Modules[moduleIndex];

                    if (thisPartModule is CNConstellationAntennaModule) // is it CNConstellationAntennaModule?
                    {
                        if (!this.Vessel.loaded)
                        {
                            partModuleSnapshot = partSnapshot.FindModule(thisPartModule, moduleIndex);

                            newAntennaPartInfo.frequency = short.Parse(partModuleSnapshot.moduleValues.GetValue("Frequency"));
                            string oname = partModuleSnapshot.moduleValues.GetValue("OptionalName");
                            newAntennaPartInfo.name     = (oname.Length == 0) ? partSnapshot.partInfo.title : oname;
                            newAntennaPartInfo.inUse    = bool.Parse(partModuleSnapshot.moduleValues.GetValue("InUse"));
                            newAntennaPartInfo.CosAngle = double.Parse(partModuleSnapshot.moduleValues.GetValue("CosAngle"));
                        }
                        else
                        {
                            CNConstellationAntennaModule antennaMod = (CNConstellationAntennaModule)thisPartModule;
                            newAntennaPartInfo.frequency = antennaMod.Frequency;
                            newAntennaPartInfo.name      = antennaMod.Name;
                            newAntennaPartInfo.inUse     = antennaMod.InUse;
                        }

                        populatedAntennaInfo = true;
                    }
                    else if (thisPartModule is ICommAntenna) // is it ModuleDataTransmitter?
                    {
                        ICommAntenna thisAntenna = thisPartModule as ICommAntenna;

                        if (!this.Vessel.loaded)
                        {
                            partModuleSnapshot = partSnapshot.FindModule(thisPartModule, moduleIndex);
                        }

                        newAntennaPartInfo.antennaPower              = (!this.vessel.loaded) ? thisAntenna.CommPowerUnloaded(partModuleSnapshot) : thisAntenna.CommPower;
                        newAntennaPartInfo.antennaCombinable         = thisAntenna.CommCombinable;
                        newAntennaPartInfo.antennaCombinableExponent = thisAntenna.CommCombinableExponent;
                        newAntennaPartInfo.antennaType           = thisAntenna.CommType;
                        newAntennaPartInfo.partReference         = thisPart; //unique ID for part is not available
                        newAntennaPartInfo.partSnapshotReference = partSnapshot;
                        newAntennaPartInfo.canComm = (!this.vessel.loaded) ? thisAntenna.CanCommUnloaded(partModuleSnapshot) : thisAntenna.CanComm();

                        populatedAntennaInfo = true;
                    }
                }

                if (populatedAntennaInfo) // valid info?
                {
                    antennas.Add(newAntennaPartInfo);
                    CNCLog.Debug("CommNet Vessel '{0}' has antenna '{1}' of {2} and {3} power (w/o range modifier)", this.Vessel.GetName(), newAntennaPartInfo.name, newAntennaPartInfo.frequency, newAntennaPartInfo.antennaPower);
                }
            }

            return(antennas);
        }