コード例 #1
0
        private IEnumerator Transmit()
        {
            var msg        = new ScreenMessage(String.Format("[{0}]: Starting Transmission...", part.partInfo.title), 4f, ScreenMessageStyle.UPPER_LEFT);
            var msg_status = new ScreenMessage(String.Empty, 4.0f, ScreenMessageStyle.UPPER_LEFT);

            ScreenMessages.PostScreenMessage(msg);

            mBusy = true;

            while (mQueue.Any())
            {
                RnDCommsStream commStream   = null;
                var            science_data = mQueue[0];
                var            data_amount  = science_data.dataAmount;
                mQueue.RemoveAt(0);
                var subject = ResearchAndDevelopment.GetSubjectByID(science_data.subjectID);
                int packets = Mathf.CeilToInt(science_data.dataAmount / PacketSize);
                if (ResearchAndDevelopment.Instance != null)
                {
                    // pre calculate the time interval - fix for x64 systems
                    // workaround for issue #136
                    float time1 = Time.time;
                    yield return(new WaitForSeconds(PacketInterval));

                    // get the delta time
                    float x64PacketInterval = (Time.time - time1);

                    RTLog.Notify("Changing RnDCommsStream timeout from {0} to {1}", PacketInterval, x64PacketInterval);

                    commStream = new RnDCommsStream(subject, science_data.dataAmount, x64PacketInterval,
                                                    science_data.transmitValue, ResearchAndDevelopment.Instance);
                }
                //StartCoroutine(SetFXModules_Coroutine(modules_progress, 0.0f));
                float power = 0;
                while (packets > 0)
                {
                    power += part.RequestResource("ElectricCharge", PacketResourceCost - power);
                    if (power >= PacketResourceCost * 0.95)
                    {
                        float frame = Math.Min(PacketSize, data_amount);
                        power       -= PacketResourceCost;
                        GUI_Status   = "Uploading Data...";
                        data_amount -= frame;
                        packets--;
                        float progress = (science_data.dataAmount - data_amount) / science_data.dataAmount;
                        //StartCoroutine(SetFXModules_Coroutine(modules_progress, progress));
                        msg_status.message = String.Format("[{0}]: Uploading Data... {1}", part.partInfo.title, progress.ToString("P0"));
                        RTLog.Notify("[Transmitter]: Uploading Data... ({0}) - {1} Mits/sec. Packets to go: {2} - Files to Go: {3}",
                                     science_data.title, (PacketSize / PacketInterval).ToString("0.00"), packets, mQueue.Count);
                        ScreenMessages.PostScreenMessage(msg_status, true);
                        if (commStream != null)
                        {
                            commStream.StreamData(frame);
                        }
                    }
                    else
                    {
                        msg.message = String.Format("<b><color=orange>[{0}]: Warning! Not Enough {1}!</color></b>", part.partInfo.title, RequiredResource);
                        ScreenMessages.PostScreenMessage(msg, true);
                        GUI_Status = String.Format("{0}/{1} {2}", power, PacketResourceCost, RequiredResource);
                    }
                    yield return(new WaitForSeconds(PacketInterval));
                }
                yield return(new WaitForSeconds(PacketInterval * 2));
            }
            mBusy       = false;
            msg.message = String.Format("[{0}]: Done!", part.partInfo.title);
            ScreenMessages.PostScreenMessage(msg, true);
            GUI_Status = "Idle";
            yield break;
        }
コード例 #2
0
        private IEnumerator Transmit(Callback callback = null)
        {
            RTLog.Notify("ModuleRTDataTransmitter::Transmit");
            var msg       = new ScreenMessage(String.Format("[{0}]: Starting Transmission...", part.partInfo.title), 4f, ScreenMessageStyle.UPPER_LEFT);
            var msgStatus = new ScreenMessage(String.Empty, 4.0f, ScreenMessageStyle.UPPER_LEFT);

            ScreenMessages.PostScreenMessage(msg);

            isBusy = true;

            while (scienceDataQueue.Any())
            {
                var scienceData = scienceDataQueue[0];
                var dataAmount  = scienceData.dataAmount;
                scienceDataQueue.RemoveAt(0);
                bool aborted = false;

                var subject = ResearchAndDevelopment.GetSubjectByID(scienceData.subjectID);
                if (subject == null)
                {
                    subject = new ScienceSubject("", "", 1, 0, 0);
                }

                int packets = Mathf.CeilToInt(scienceData.dataAmount / PacketSize);

                RnDCommsStream commStream = null;
                if (ResearchAndDevelopment.Instance != null && !scienceData.triggered)
                {
                    // pre-calculate the time interval - fix for x64 systems
                    // workaround for issue #136
                    //float time1 = Time.time;
                    //yield return new WaitForSeconds(PacketInterval);

                    // get the delta time
                    //float x64PacketInterval = (Time.time - time1);
                    //RTLog.Notify("Changing RnDCommsStream timeout from {0} to {1}", PacketInterval, x64PacketInterval);

                    //(porting to 1.2): check if scienceData.baseTransmitValue alone or with scienceData.transmitBonus
                    //commStream = new RnDCommsStream(subject, scienceData.dataAmount, x64PacketInterval,
                    commStream = new RnDCommsStream(subject, scienceData.dataAmount, PacketInterval,
                                                    scienceData.baseTransmitValue, false, ResearchAndDevelopment.Instance);
                }
                //StartCoroutine(SetFXModules_Coroutine(modules_progress, 0.0f));
                float power = 0;
                timeElapsed = 0;
                while (packets > 0)
                {
                    if (timeElapsed >= PacketInterval)
                    {
                        timeElapsed -= PacketInterval;
                        power       += part.RequestResource("ElectricCharge", PacketResourceCost - power);
                        if (power >= PacketResourceCost * 0.95)
                        {
                            GUIStatus = "Uploading Data...";

                            // remove some power due to transmission
                            power -= PacketResourceCost;

                            // transmitted size
                            float frame = Math.Min(PacketSize, dataAmount);

                            // subtract current packet size from data left to transmit
                            // and clamp it to 1 digit precision to avoid large float precision error (#667)
                            dataAmount -= frame;
                            dataAmount  = (float)Math.Round(dataAmount, 1);

                            packets--;

                            float progress = (scienceData.dataAmount - dataAmount) / scienceData.dataAmount;
                            msgStatus.message = String.Format("[{0}]: Uploading Data... {1:P0}", part.partInfo.title, progress);
                            ScreenMessages.PostScreenMessage(msgStatus);

                            RTLog.Notify("[Transmitter]: Uploading Data... ({0}) - {1} Mits/sec. Packets to go: {2} - Other experiments waiting to transfer: {3}",
                                         scienceData.title, (PacketSize / PacketInterval).ToString("0.00"), packets, scienceDataQueue.Count);

                            // if we've a defined callback parameter so skip to stream each packet
                            if (commStream != null)
                            {
                                RTLog.Notify(
                                    "[Transmitter]: PacketSize: {0}; Transmitted size (frame): {1}; Data left to transmit (dataAmount): {2}; Packets left (packets): {3}",
                                    PacketSize, frame, dataAmount, packets);

                                // use try / catch to prevent NRE spamming in KSP code when RT is used with other mods.
                                try
                                {
                                    // check if it's the last packet to send
                                    if (packets == 0)
                                    {
                                        // issue #667, issue #714 ; floating point error in RnDCommsStream.StreamData method when adding to dataIn private field
                                        // e.g scienceData.dataAmount is 10 but in the end RnDCommsStream.dataIn will be 9.999999, so the science never
                                        //     gets registered to the ResearchAndDevelopment center.
                                        // Let's just go ahead and send the full amount so there's no question if we sent it all
                                        // KSP will clamp the final size to PacketSize anyway.
                                        frame = scienceData.dataAmount;
                                    }

                                    commStream.StreamData(frame, vessel.protoVessel);
                                }
                                catch (NullReferenceException nre)
                                {
                                    RTLog.Notify("[Transmitter] A problem occurred during science transmission: {0}", RTLogLevel.LVL2, nre);
                                }
                            }
                            else
                            {
                                RTLog.Notify("[Transmitter]: [DEBUG] commstream is null and no callback");
                            }
                        }
                        else
                        {
                            // not enough power
                            msg.message = String.Format("<b><color=orange>[{0}]: Warning! Not Enough {1}!</color></b>", part.partInfo.title, RequiredResource);
                            ScreenMessages.PostScreenMessage(msg);
                            aborted = true;

                            GUIStatus = String.Format("{0}/{1} {2}", power, PacketResourceCost, RequiredResource);
                        }
                    }
                    yield return(new WaitForFixedUpdate());
                }

                // effectively inform the game that science has been transmitted
                if (scienceData.triggered)
                {
                    GameEvents.OnTriggeredDataTransmission.Fire(scienceData, vessel, aborted);
                }

                yield return(new WaitForSeconds(PacketInterval * 2));
            }

            isBusy = false;

            msg.message = String.Format("[{0}]: Done!", part.partInfo.title);
            ScreenMessages.PostScreenMessage(msg);

            if (callback != null)
            {
                callback.Invoke();
            }

            GUIStatus = "Idle";
        }
コード例 #3
0
        private IEnumerator Transmit(Callback callback = null)
        {
            RTLog.Notify("ModuleRTDataTransmitter::Transmit");
            var msg = new ScreenMessage(String.Format("[{0}]: Starting Transmission...", part.partInfo.title), 4f, ScreenMessageStyle.UPPER_LEFT);
            var msgStatus = new ScreenMessage(String.Empty, 4.0f, ScreenMessageStyle.UPPER_LEFT);
            ScreenMessages.PostScreenMessage(msg);

            isBusy = true;

            while (scienceDataQueue.Any())
            {
                var scienceData = scienceDataQueue[0];
                var dataAmount = scienceData.dataAmount;
                scienceDataQueue.RemoveAt(0);
                scienceData.triggered = true;

                var subject = ResearchAndDevelopment.GetSubjectByID(scienceData.subjectID);
                if (subject == null)
                    subject = new ScienceSubject("", "", 1, 0, 0);

                int packets = Mathf.CeilToInt(scienceData.dataAmount / PacketSize);

                RnDCommsStream commStream = null;
                if (ResearchAndDevelopment.Instance != null)
                {
                    // pre-calculate the time interval - fix for x64 systems
                    // workaround for issue #136
                    float time1 = Time.time;
                    yield return new WaitForSeconds(PacketInterval);

                    // get the delta time
                    float x64PacketInterval = (Time.time - time1);
                    RTLog.Notify("Changing RnDCommsStream timeout from {0} to {1}", PacketInterval, x64PacketInterval);

                    //TODO (porting to 1.2): check if scienceData.baseTransmitValue alone or with scienceData.transmitBonus
                    commStream = new RnDCommsStream(subject, scienceData.dataAmount, x64PacketInterval,
                                            scienceData.baseTransmitValue, false, ResearchAndDevelopment.Instance);
                }
                //StartCoroutine(SetFXModules_Coroutine(modules_progress, 0.0f));
                float power = 0;
                while (packets > 0)
                {
                    power += part.RequestResource("ElectricCharge", PacketResourceCost - power);
                    if (power >= PacketResourceCost * 0.95)
                    {
                        GUIStatus = "Uploading Data...";

                        // remove some power due to transmission
                        power -= PacketResourceCost;

                        // transmitted size
                        float frame = Math.Min(PacketSize, dataAmount);

                        // subtract current packet size from data left to transmit
                        // and clamp it to 1 digit precision to avoid large float precision error (#667)
                        dataAmount -= frame;
                        dataAmount = (float)Math.Round(dataAmount, 1);

                        packets--;

                        float progress = (scienceData.dataAmount - dataAmount) / scienceData.dataAmount;
                        msgStatus.message = String.Format("[{0}]: Uploading Data... {1:P0}", part.partInfo.title, progress);
                        ScreenMessages.PostScreenMessage(msgStatus);

                        RTLog.Notify("[Transmitter]: Uploading Data... ({0}) - {1} Mits/sec. Packets to go: {2} - Other experiments waiting to transfer: {3}",
                            scienceData.title, (PacketSize / PacketInterval).ToString("0.00"), packets, scienceDataQueue.Count);

                        // if we've a defined callback parameter so skip to stream each packet
                        if (commStream != null && callback == null)
                        {
                            RTLog.Notify(
                                "[Transmitter]: PacketSize: {0}; Transmitted size (frame): {1}; Data left to transmit (dataAmount): {2}; Packets left (packets): {3}",
                                PacketSize, frame, dataAmount, packets);

                            // use try / catch to prevent NRE spamming in KSP code when RT is used with other mods.
                            try
                            {
                                commStream.StreamData(frame, vessel.protoVessel);
                            }
                            catch (NullReferenceException nre)
                            {
                                RTLog.Notify("A problem occurred during science transmission: {0}", RTLogLevel.LVL2, nre);
                            }

                            // TODO: remove this when fixed in stock
                            // Fix a problem in stock KSP (discovered in 1.1.3, and still here in 1.2.1)
                            // issue #667 ; floating point error in RnDCommsStream.StreamData method when adding to dataIn private field
                            // e.g scienceData.dataAmount is 10 but in the end RnDCommsStream.dataIn will be 9.999999, so the science never
                            //     gets registered to the ResearchAndDevelopment center.
                            if (packets == 0) // check that we have no packet left to send.
                            {
                                // get the private field (dataIn) in RnDCommsStream. This field is subject to floating point rounding error
                                // We handle this problem on our side.
                                var dataIn = RTUtil.GetInstanceField(typeof(RnDCommsStream), commStream, "dataIn");
                                if (dataIn != null)
                                {
                                    // check if we have a delta (e.g. 10 - 9.999999999 will give us a tiny delta)
                                    var delta = scienceData.dataAmount - (float) dataIn;
                                    RTLog.Notify("[Transmitter]: delta: {0}", delta);

                                    // the delta must be positive and less than this constant to push / transmit the remaining size.
                                    // This prevent us pushing packets with too much leftover to transmit (e.g if there was a connection loss).
                                    if ((delta > 0f) && (delta <= PacketRemainingSize))
                                    {
                                        try
                                        {
                                            // we have a delta, try to send the remaining little bit of science
                                            commStream.StreamData(delta, vessel.protoVessel);
                                        }
                                        catch (NullReferenceException nre)
                                        {
                                            RTLog.Notify("A problem occurred during science transmission (delta): {0}",
                                                RTLogLevel.LVL2, nre);
                                        }
                                    }
                                }
                                else
                                {
                                    RTLog.Notify("[Transmitter]: dataIn is null.");
                                }
                            } // end stock fix
                        }
                        else
                        {
                            RTLog.Notify("[Transmitter]: [DEBUG] commstream is null and no callback");
                        }
                    }
                    else
                    {
                        // not enough power
                        msg.message = String.Format("<b><color=orange>[{0}]: Warning! Not Enough {1}!</color></b>", part.partInfo.title, RequiredResource);
                        ScreenMessages.PostScreenMessage(msg);

                        GUIStatus = String.Format("{0}/{1} {2}", power, PacketResourceCost, RequiredResource);
                    }

                    yield return new WaitForSeconds(PacketInterval);
                }

                // effectively inform the game that science has been transmitted
                GameEvents.OnTriggeredDataTransmission.Fire(scienceData, vessel, false);
                yield return new WaitForSeconds(PacketInterval * 2);
            }

            isBusy = false;

            msg.message = String.Format("[{0}]: Done!", part.partInfo.title);
            ScreenMessages.PostScreenMessage(msg);

            if (callback != null)
                callback.Invoke();

            GUIStatus = "Idle";
        }
コード例 #4
0
        private IEnumerator Transmit()
        {
            var msg = new ScreenMessage(String.Format("[{0}]: Starting Transmission...", part.partInfo.title), 4f, ScreenMessageStyle.UPPER_LEFT);
            var msg_status = new ScreenMessage(String.Empty, 4.0f, ScreenMessageStyle.UPPER_LEFT);
            ScreenMessages.PostScreenMessage(msg);

            mBusy = true;

            while (mQueue.Any())
            {
                RnDCommsStream commStream = null;
                var science_data = mQueue[0];
                var data_amount = science_data.dataAmount;
                mQueue.RemoveAt(0);
                var subject = ResearchAndDevelopment.GetSubjectByID(science_data.subjectID);
                int packets = Mathf.CeilToInt(science_data.dataAmount / PacketSize);
                if (ResearchAndDevelopment.Instance != null)
                {
                    commStream = new RnDCommsStream(subject, science_data.dataAmount, PacketInterval,
                        science_data.transmitValue, ResearchAndDevelopment.Instance);
                }
                //StartCoroutine(SetFXModules_Coroutine(modules_progress, 0.0f));
                float power = 0;
                while (packets > 0)
                {
                    power += part.RequestResource("ElectricCharge", PacketResourceCost - power);
                    if (power >= PacketResourceCost * 0.95)
                    {
                        float frame = Math.Min(PacketSize, data_amount);
                        power -= PacketResourceCost;
                        GUI_Status = "Uploading Data...";
                        data_amount -= frame;
                        packets--;
                        float progress = (science_data.dataAmount - data_amount) / science_data.dataAmount;
                        //StartCoroutine(SetFXModules_Coroutine(modules_progress, progress));
                        msg_status.message = String.Format("[{0}]: Uploading Data... {1}", part.partInfo.title, progress.ToString("P0"));
                        RTLog.Notify("[Transmitter]: Uploading Data... ({0}) - {1} Mits/sec. Packets to go: {2} - Files to Go: {3}",
                            science_data.title, (PacketSize / PacketInterval).ToString("0.00"), packets, mQueue.Count);
                        ScreenMessages.PostScreenMessage(msg_status, true);
                        if (commStream != null)
                        {
                            commStream.StreamData(frame);
                        }
                    }
                    else
                    {
                        msg.message = String.Format("<b><color=orange>[{0}]: Warning! Not Enough {1}!</color></b>", part.partInfo.title, RequiredResource);
                        ScreenMessages.PostScreenMessage(msg, true);
                        GUI_Status = String.Format("{0}/{1} {2}", power, PacketResourceCost, RequiredResource);

                    }
                    yield return new WaitForSeconds(PacketInterval);
                }
                yield return new WaitForSeconds(PacketInterval * 2);
            }
            mBusy = false;
            msg.message = String.Format("[{0}]: Done!", part.partInfo.title);
            ScreenMessages.PostScreenMessage(msg, true);
            GUI_Status = "Idle";
            yield break;
        }
コード例 #5
0
        private IEnumerator Transmit(Callback callback = null)
        {
            RTLog.Notify("ModuleRTDataTransmitter::Transmit");
            var msg       = new ScreenMessage(String.Format("[{0}]: Starting Transmission...", part.partInfo.title), 4f, ScreenMessageStyle.UPPER_LEFT);
            var msgStatus = new ScreenMessage(String.Empty, 4.0f, ScreenMessageStyle.UPPER_LEFT);

            ScreenMessages.PostScreenMessage(msg);

            isBusy = true;

            while (scienceDataQueue.Any())
            {
                var scienceData = scienceDataQueue[0];
                var dataAmount  = scienceData.dataAmount;
                scienceDataQueue.RemoveAt(0);
                scienceData.triggered = true;

                var subject = ResearchAndDevelopment.GetSubjectByID(scienceData.subjectID);
                if (subject == null)
                {
                    subject = new ScienceSubject("", "", 1, 0, 0);
                }

                int packets = Mathf.CeilToInt(scienceData.dataAmount / PacketSize);

                RnDCommsStream commStream = null;
                if (ResearchAndDevelopment.Instance != null)
                {
                    // pre-calculate the time interval - fix for x64 systems
                    // workaround for issue #136
                    float time1 = Time.time;
                    yield return(new WaitForSeconds(PacketInterval));

                    // get the delta time
                    float x64PacketInterval = (Time.time - time1);
                    RTLog.Notify("Changing RnDCommsStream timeout from {0} to {1}", PacketInterval, x64PacketInterval);

                    //TODO (porting to 1.2): check if scienceData.baseTransmitValue alone or with scienceData.transmitBonus
                    commStream = new RnDCommsStream(subject, scienceData.dataAmount, x64PacketInterval,
                                                    scienceData.baseTransmitValue, false, ResearchAndDevelopment.Instance);
                }
                //StartCoroutine(SetFXModules_Coroutine(modules_progress, 0.0f));
                float power = 0;
                while (packets > 0)
                {
                    power += part.RequestResource("ElectricCharge", PacketResourceCost - power);
                    if (power >= PacketResourceCost * 0.95)
                    {
                        GUIStatus = "Uploading Data...";

                        // remove some power due to transmission
                        power -= PacketResourceCost;

                        // transmitted size
                        float frame = Math.Min(PacketSize, dataAmount);

                        // subtract current packet size from data left to transmit
                        // and clamp it to 1 digit precision to avoid large float precision error (#667)
                        dataAmount -= frame;
                        dataAmount  = (float)Math.Round(dataAmount, 1);

                        packets--;

                        float progress = (scienceData.dataAmount - dataAmount) / scienceData.dataAmount;
                        msgStatus.message = String.Format("[{0}]: Uploading Data... {1:P0}", part.partInfo.title, progress);
                        ScreenMessages.PostScreenMessage(msgStatus);

                        RTLog.Notify("[Transmitter]: Uploading Data... ({0}) - {1} Mits/sec. Packets to go: {2} - Other experiments waiting to transfer: {3}",
                                     scienceData.title, (PacketSize / PacketInterval).ToString("0.00"), packets, scienceDataQueue.Count);

                        // if we've a defined callback parameter so skip to stream each packet
                        if (commStream != null && callback == null)
                        {
                            RTLog.Notify(
                                "[Transmitter]: PacketSize: {0}; Transmitted size (frame): {1}; Data left to transmit (dataAmount): {2}; Packets left (packets): {3}",
                                PacketSize, frame, dataAmount, packets);

                            // use try / catch to prevent NRE spamming in KSP code when RT is used with other mods.
                            try
                            {
                                commStream.StreamData(frame, vessel.protoVessel);
                            }
                            catch (NullReferenceException nre)
                            {
                                RTLog.Notify("A problem occurred during science transmission: {0}", RTLogLevel.LVL2, nre);
                            }

                            // TODO: remove this when fixed in stock
                            // Fix a problem in stock KSP (discovered in 1.1.3, and still here in 1.2.1)
                            // issue #667 ; floating point error in RnDCommsStream.StreamData method when adding to dataIn private field
                            // e.g scienceData.dataAmount is 10 but in the end RnDCommsStream.dataIn will be 9.999999, so the science never
                            //     gets registered to the ResearchAndDevelopment center.
                            if (packets == 0) // check that we have no packet left to send.
                            {
                                // get the private field (dataIn) in RnDCommsStream. This field is subject to floating point rounding error
                                // We handle this problem on our side.
                                var dataIn = RTUtil.GetInstanceField(typeof(RnDCommsStream), commStream, "dataIn");
                                if (dataIn != null)
                                {
                                    // check if we have a delta (e.g. 10 - 9.999999999 will give us a tiny delta)
                                    var delta = scienceData.dataAmount - (float)dataIn;
                                    RTLog.Notify("[Transmitter]: delta: {0}", delta);

                                    // the delta must be positive and less than this constant to push / transmit the remaining size.
                                    // This prevent us pushing packets with too much leftover to transmit (e.g if there was a connection loss).
                                    if ((delta > 0f) && (delta <= PacketRemainingSize))
                                    {
                                        try
                                        {
                                            // we have a delta, try to send the remaining little bit of science
                                            commStream.StreamData(delta, vessel.protoVessel);
                                        }
                                        catch (NullReferenceException nre)
                                        {
                                            RTLog.Notify("A problem occurred during science transmission (delta): {0}",
                                                         RTLogLevel.LVL2, nre);
                                        }
                                    }
                                }
                                else
                                {
                                    RTLog.Notify("[Transmitter]: dataIn is null.");
                                }
                            } // end stock fix
                        }
                        else
                        {
                            RTLog.Notify("[Transmitter]: [DEBUG] commstream is null and no callback");
                        }
                    }
                    else
                    {
                        // not enough power
                        msg.message = String.Format("<b><color=orange>[{0}]: Warning! Not Enough {1}!</color></b>", part.partInfo.title, RequiredResource);
                        ScreenMessages.PostScreenMessage(msg);

                        GUIStatus = String.Format("{0}/{1} {2}", power, PacketResourceCost, RequiredResource);
                    }

                    yield return(new WaitForSeconds(PacketInterval));
                }

                // effectively inform the game that science has been transmitted
                GameEvents.OnTriggeredDataTransmission.Fire(scienceData, vessel, false);
                yield return(new WaitForSeconds(PacketInterval * 2));
            }

            isBusy = false;

            msg.message = String.Format("[{0}]: Done!", part.partInfo.title);
            ScreenMessages.PostScreenMessage(msg);

            if (callback != null)
            {
                callback.Invoke();
            }

            GUIStatus = "Idle";
        }
コード例 #6
0
        private IEnumerator Transmit(Callback callback = null)
        {
            var msg = new ScreenMessage(String.Format("[{0}]: Starting Transmission...", part.partInfo.title), 4f, ScreenMessageStyle.UPPER_LEFT);
            var msgStatus = new ScreenMessage(String.Empty, 4.0f, ScreenMessageStyle.UPPER_LEFT);
            ScreenMessages.PostScreenMessage(msg);

            isBusy = true;

            while (scienceDataQueue.Any())
            {
                RnDCommsStream commStream = null;
                var scienceData = scienceDataQueue[0];
                var dataAmount = scienceData.dataAmount;
                scienceDataQueue.RemoveAt(0);
                var subject = ResearchAndDevelopment.GetSubjectByID(scienceData.subjectID);
                int packets = Mathf.CeilToInt(scienceData.dataAmount / PacketSize);
                if (ResearchAndDevelopment.Instance != null)
                {
                    // pre calculate the time interval - fix for x64 systems
                    // workaround for issue #136
                    float time1 = Time.time;
                    yield return new WaitForSeconds(PacketInterval);
                    // get the delta time
                    float x64PacketInterval = (Time.time - time1);

                    RTLog.Notify("Changing RnDCommsStream timeout from {0} to {1}", PacketInterval, x64PacketInterval);

                    commStream = new RnDCommsStream(subject, scienceData.dataAmount, x64PacketInterval,
                                            scienceData.transmitValue, false, ResearchAndDevelopment.Instance);
                }
                //StartCoroutine(SetFXModules_Coroutine(modules_progress, 0.0f));
                float power = 0;
                while (packets > 0)
                {
                    power += part.RequestResource("ElectricCharge", PacketResourceCost - power);
                    if (power >= PacketResourceCost * 0.95)
                    {
                        float frame = Math.Min(PacketSize, dataAmount);
                        power -= PacketResourceCost;
                        GUIStatus = "Uploading Data...";
                        dataAmount -= frame;
                        packets--;
                        float progress = (scienceData.dataAmount - dataAmount) / scienceData.dataAmount;
                        //StartCoroutine(SetFXModules_Coroutine(modules_progress, progress));
                        msgStatus.message = String.Format("[{0}]: Uploading Data... {1}", part.partInfo.title, progress.ToString("P0"));
                        RTLog.Notify("[Transmitter]: Uploading Data... ({0}) - {1} Mits/sec. Packets to go: {2} - Files to Go: {3}",
                            scienceData.title, (PacketSize / PacketInterval).ToString("0.00"), packets, scienceDataQueue.Count);
                        ScreenMessages.PostScreenMessage(msgStatus, true);

                        // if we've a defined callback parameter so skip to stream each packet
                        if (commStream != null && callback == null)
                        {
                            commStream.StreamData(frame, vessel.protoVessel);
                        }
                    }
                    else
                    {
                        msg.message = String.Format("<b><color=orange>[{0}]: Warning! Not Enough {1}!</color></b>", part.partInfo.title, RequiredResource);
                        ScreenMessages.PostScreenMessage(msg, true);
                        GUIStatus = String.Format("{0}/{1} {2}", power, PacketResourceCost, RequiredResource);
                    }
                    yield return new WaitForSeconds(PacketInterval);
                }
                yield return new WaitForSeconds(PacketInterval * 2);
            }
            isBusy = false;
            msg.message = String.Format("[{0}]: Done!", part.partInfo.title);
            ScreenMessages.PostScreenMessage(msg, true);
            if (callback != null) callback.Invoke();
            GUIStatus = "Idle";
        }