Esempio n. 1
0
        public static void CreateControlTextbox(string id, string title, string tooltip, Func <IMyTerminalBlock, bool> visible, Func <IMyTerminalBlock, bool> enabled, Func <IMyTerminalBlock, StringBuilder> getter, Action <IMyTerminalBlock, StringBuilder> setter)
        {
            if (ControlIdExists(id) != null)
            {
                return;
            }

            IMyTerminalControlTextbox textbox = MyAPIGateway.TerminalControls.CreateControl <IMyTerminalControlTextbox, IMyUpgradeModule>(id);

            textbox.Enabled = enabled;
            textbox.Visible = visible;
            textbox.SupportsMultipleBlocks = false;

            if (title != null)
            {
                textbox.Title = MyStringId.GetOrCompute(title);
            }
            if (tooltip != null)
            {
                textbox.Tooltip = MyStringId.GetOrCompute(tooltip);
            }

            textbox.Getter = getter;

            if (setter != null)
            {
                textbox.Setter = setter;
            }

            MyAPIGateway.TerminalControls.AddControl <IMyUpgradeModule>(textbox);
        }
Esempio n. 2
0
        private void InitControls()
        {
            _showQrControl        = MyAPIGateway.TerminalControls.CreateControl <IMyTerminalControlCheckbox, IMyTextPanel>("");
            _showQrControl.Title  = MyStringId.GetOrCompute("Show QR Code");
            _showQrControl.Getter = b => ((IMyTextPanel)b).ShowOnScreen == ShowTextOnScreenFlag.PUBLIC;
            _showQrControl.Setter = (b, v) =>
            {
                ((IMyTextPanel)b).SetShowOnScreen(v ? ShowTextOnScreenFlag.PUBLIC : ShowTextOnScreenFlag.NONE);
            };

            _keyControl        = MyAPIGateway.TerminalControls.CreateControl <IMyTerminalControlTextbox, IMyTextPanel>("");
            _keyControl.Title  = MyStringId.GetOrCompute("API Key");
            _keyControl.Getter = b =>
            {
                var logic = b.GameLogic.GetAs <WebApiBlockComp>();
                if (string.IsNullOrEmpty(logic?.LocalKey))
                {
                    RequestKey(b);
                }

                return(new StringBuilder(logic?.LocalKey ?? ""));
            };
            _keyControl.Setter = (b, v) => { };

            _genControl        = MyAPIGateway.TerminalControls.CreateControl <IMyTerminalControlButton, IMyTextPanel>("");
            _genControl.Title  = MyStringId.GetOrCompute("Generate New Key");
            _genControl.Action = b => RequestKey(b, true);
        }
Esempio n. 3
0
        /// <summary>
        /// Synchronize and save a StringBuilder associated with a MyTerminalControlTextbox. The StringBuilder is synchronized from time to time.
        /// </summary>
        /// <param name="control">GUI control for getting/setting the value.</param>
        /// <param name="fieldName">The name of a field in the script to get/set the value from/to.</param>
        /// <param name="save">Iff true, save the value to disk.</param>
        public StringBuilderSync(IMyTerminalControlTextbox control, string fieldName, bool save = true)
            : base(((IMyTerminalControl)control).Id, fieldName, save)
        {
            // MyTerminalControlTextbox has different Getter/Setter
            control.Getter = GetValue;
            control.Setter = SetValue;

            _control = control;
        }
Esempio n. 4
0
        /// <summary>
        /// Synchronize and save a StringBuilder associated with a MyTerminalControlTextbox. The StringBuilder is synchronized from time to time.
        /// </summary>
        /// <param name="control">GUI control for getting/setting the value.</param>
        /// <param name="getter">Function to get the StringBuilder from a script.</param>
        /// <param name="setter">Function to set a StringBuilder in a script.</param>
        /// <param name="save">Iff true, save the value to disk.</param>
        public StringBuilderSync(IMyTerminalControlTextbox control, GetterDelegate getter, SetterDelegate setter, bool save = true)
            : base(((IMyTerminalControl)control).Id, getter, setter, save)
        {
            // MyTerminalControlTextbox has different Getter/Setter
            control.Getter = GetValue;
            control.Setter = SetValue;

            _control = control;
        }
Esempio n. 5
0
        public TypedValueSync(IMyTerminalControlTextbox control, GetterDelegate getter, SetterDelegate setter, bool save = true, TValue defaultValue = default(TValue))
            : base(((IMyTerminalControl)control).Id, getter, setter, save, defaultValue)
        {
            // MyTerminalControlTextbox has different Getter/Setter
            control.Getter = GetStringBuilder;
            control.Setter = SetStringBuilder;

            _control = control;
        }
        public TerminalTextBox(IMyTerminalControlTextbox terminalControl, byte valueId, Action <EntityValue <T> > onValueChanged, T invalidValue = default(T))
        {
            m_invalidValue   = invalidValue;
            m_valueId        = valueId;
            m_onValueChanged = onValueChanged;

            terminalControl.Getter = TC_Getter;
            terminalControl.Setter = TC_Setter;

            Update.UpdateManager.Register(100, Update100);
        }
Esempio n. 7
0
        static void createUI()
        {
            if (m_controlsInit)
            {
                return;
            }

            m_controlsInit = true;

            MyAPIGateway.TerminalControls.CustomControlGetter -= customControlGetter;

            MyAPIGateway.TerminalControls.CustomControlGetter += customControlGetter;

            // sender/receiver switch
            m_controlSender         = MyAPIGateway.TerminalControls.CreateControl <IMyTerminalControlOnOffSwitch, IMyRefinery>("Cython.RPT.SenderReceiver");
            m_controlSender.Enabled = (b) => true;
            m_controlSender.Visible = (b) => b.BlockDefinition.SubtypeId.Equals("LargeBlockSmallRadialPowerTransmitter") || b.BlockDefinition.SubtypeId.Equals("SmallBlockSmallRadialPowerTransmitter");
            m_controlSender.Title   = MyStringId.GetOrCompute("Mode");
            m_controlSender.Tooltip = MyStringId.GetOrCompute("Switches this transmitters mode to Sender or Receiver");
            m_controlSender.OnText  = MyStringId.GetOrCompute("Send");
            m_controlSender.OffText = MyStringId.GetOrCompute("Rec.");
            m_controlSender.Getter  = (b) => b.GameLogic.GetAs <RadialPowerTransmitter>().m_sender;
            m_controlSender.Setter  = (b, v) => {
                b.GameLogic.GetAs <RadialPowerTransmitter>().m_sender      = v;
                b.GameLogic.GetAs <RadialPowerTransmitter>().m_info.sender = v;

                m_controlSender.UpdateVisual();
                m_controlPower.UpdateVisual();

                byte[] message   = new byte[13];
                byte[] messageId = BitConverter.GetBytes(0);
                byte[] entityId  = BitConverter.GetBytes(b.EntityId);

                for (int i = 0; i < 4; i++)
                {
                    message[i] = messageId[i];
                }

                for (int i = 0; i < 8; i++)
                {
                    message[i + 4] = entityId[i];
                }

                message[12] = BitConverter.GetBytes(v)[0];


                MyAPIGateway.Multiplayer.SendMessageToOthers(5910, message, true);
            };
            MyAPIGateway.TerminalControls.AddControl <IMyRefinery>(m_controlSender);

            // channel field
            m_controlChannel         = MyAPIGateway.TerminalControls.CreateControl <IMyTerminalControlTextbox, IMyRefinery>("Cython.RPT.Channel");
            m_controlChannel.Enabled = (b) => true;
            m_controlChannel.Visible = (b) => b.BlockDefinition.SubtypeId.Equals("LargeBlockSmallRadialPowerTransmitter") || b.BlockDefinition.SubtypeId.Equals("SmallBlockSmallRadialPowerTransmitter");
            m_controlChannel.Title   = MyStringId.GetOrCompute("Channel");
            m_controlChannel.Tooltip = MyStringId.GetOrCompute("Channel this transmitter is supposed to send or receive on.");
            m_controlChannel.Getter  = (b) => (new StringBuilder()).Append(b.GameLogic.GetAs <RadialPowerTransmitter>().m_channel);
            m_controlChannel.Setter  = (b, s) => {
                uint channel;

                if (uint.TryParse(s.ToString(), out channel))
                {
                    var RPT = b.GameLogic.GetAs <RadialPowerTransmitter>();

                    RPT.m_channel      = channel;
                    RPT.m_info.channel = channel;

                    byte[] message   = new byte[16];
                    byte[] messageId = BitConverter.GetBytes(1);
                    byte[] entityId  = BitConverter.GetBytes(b.EntityId);
                    byte[] value     = BitConverter.GetBytes(channel);

                    for (int i = 0; i < 4; i++)
                    {
                        message[i] = messageId[i];
                    }

                    for (int i = 0; i < 8; i++)
                    {
                        message[i + 4] = entityId[i];
                    }

                    for (int i = 0; i < 4; i++)
                    {
                        message[i + 12] = value[i];
                    }

                    MyAPIGateway.Multiplayer.SendMessageToOthers(5910, message, true);
                }
            };

            MyAPIGateway.TerminalControls.AddControl <IMyRefinery>(m_controlChannel);

            // power field
            m_controlPower         = MyAPIGateway.TerminalControls.CreateControl <IMyTerminalControlTextbox, IMyRefinery>("Cython.RPT.Power");
            m_controlPower.Enabled = (b) => b.GameLogic.GetAs <RadialPowerTransmitter>().m_sender;
            m_controlPower.Visible = (b) => b.BlockDefinition.SubtypeId.Equals("LargeBlockSmallRadialPowerTransmitter") || b.BlockDefinition.SubtypeId.Equals("SmallBlockSmallRadialPowerTransmitter");
            m_controlPower.Title   = MyStringId.GetOrCompute("Power");
            m_controlPower.Tooltip = MyStringId.GetOrCompute("Maximum power this transmitter is supposed to send.");
            m_controlPower.Getter  = (b) => (new StringBuilder()).Append(b.GameLogic.GetAs <RadialPowerTransmitter>().m_transmittedPower);
            m_controlPower.Setter  = (b, s) => {
                float power;

                if (float.TryParse(s.ToString(), out power))
                {
                    var RPT = b.GameLogic.GetAs <RadialPowerTransmitter>();

                    RPT.m_transmittedPower = power;

                    if (RPT.m_transmittedPower > RPT.m_currentMaxPower)
                    {
                        RPT.m_transmittedPower = RPT.m_currentMaxPower;
                    }

                    byte[] message   = new byte[16];
                    byte[] messageId = BitConverter.GetBytes(2);
                    byte[] entityId  = BitConverter.GetBytes(b.EntityId);
                    byte[] value     = BitConverter.GetBytes(RPT.m_transmittedPower);

                    for (int i = 0; i < 4; i++)
                    {
                        message[i] = messageId[i];
                    }

                    for (int i = 0; i < 8; i++)
                    {
                        message[i + 4] = entityId[i];
                    }

                    for (int i = 0; i < 4; i++)
                    {
                        message[i + 12] = value[i];
                    }

                    MyAPIGateway.Multiplayer.SendMessageToOthers(5910, message, true);
                }
            };

            MyAPIGateway.TerminalControls.AddControl <IMyRefinery>(m_controlPower);
        }
        static void createUI()
        {
            if (m_controlsInit)
            {
                return;
            }

            m_controlsInit = true;

            MyAPIGateway.TerminalControls.CustomControlGetter -= customControlGetter;

            MyAPIGateway.TerminalControls.CustomControlGetter += customControlGetter;

            // sender/receiver switch
            m_controlSender         = MyAPIGateway.TerminalControls.CreateControl <IMyTerminalControlOnOffSwitch, IMyRefinery>("Cython.OPT.SenderReceiver");
            m_controlSender.Enabled = (b) => true;
            m_controlSender.Visible = (b) => b.BlockDefinition.SubtypeId.Equals("LargeBlockSmallOpticalPowerTransmitter") || b.BlockDefinition.SubtypeId.Equals("SmallBlockSmallOpticalPowerTransmitter");
            m_controlSender.Title   = MyStringId.GetOrCompute("Mode");
            m_controlSender.Tooltip = MyStringId.GetOrCompute("Switches this transmitters mode to Sender or Receiver");
            m_controlSender.OnText  = MyStringId.GetOrCompute("Send");
            m_controlSender.OffText = MyStringId.GetOrCompute("Rec.");
            m_controlSender.Getter  = (b) => b.GameLogic.GetAs <OpticalPowerTransmitter>().m_sender;
            m_controlSender.Setter  = (b, v) => {
                b.GameLogic.GetAs <OpticalPowerTransmitter>().m_sender      = v;
                b.GameLogic.GetAs <OpticalPowerTransmitter>().m_info.sender = v;

                m_controlSender.UpdateVisual();
                m_controlPower.UpdateVisual();

                byte[] message   = new byte[13];
                byte[] messageId = BitConverter.GetBytes(3);
                byte[] entityId  = BitConverter.GetBytes(b.EntityId);

                for (int i = 0; i < 4; i++)
                {
                    message[i] = messageId[i];
                }

                for (int i = 0; i < 8; i++)
                {
                    message[i + 4] = entityId[i];
                }

                message[12] = BitConverter.GetBytes(v)[0];


                MyAPIGateway.Multiplayer.SendMessageToOthers(5910, message, true);
            };
            MyAPIGateway.TerminalControls.AddControl <IMyRefinery>(m_controlSender);

            // channel field
            m_controlId         = MyAPIGateway.TerminalControls.CreateControl <IMyTerminalControlTextbox, IMyRefinery>("Cython.OPT.ID");
            m_controlId.Enabled = (b) => true;
            m_controlId.Visible = (b) => b.BlockDefinition.SubtypeId.Equals("LargeBlockSmallOpticalPowerTransmitter") || b.BlockDefinition.SubtypeId.Equals("SmallBlockSmallOpticalPowerTransmitter");
            m_controlId.Title   = MyStringId.GetOrCompute("ID");
            m_controlId.Tooltip = MyStringId.GetOrCompute("ID this transmitter is being identified as when being receiver or it is supposed to send to.");
            m_controlId.Getter  = (b) => {
                if (b.GameLogic.GetAs <OpticalPowerTransmitter>().m_sender)
                {
                    return((new StringBuilder()).Append(b.GameLogic.GetAs <OpticalPowerTransmitter>().m_targetId));
                }
                else
                {
                    return((new StringBuilder()).Append(b.GameLogic.GetAs <OpticalPowerTransmitter>().m_id));
                }
            };

            m_controlId.Setter = (b, s) => {
                uint id;

                if (uint.TryParse(s.ToString(), out id))
                {
                    var OPT = b.GameLogic.GetAs <OpticalPowerTransmitter>();
                    if (OPT.m_sender)
                    {
                        OPT.m_targetId = id;
                    }
                    else
                    {
                        OPT.m_id      = id;
                        OPT.m_info.id = id;
                    }

                    byte[] message   = new byte[16];
                    byte[] messageId = BitConverter.GetBytes(4);
                    byte[] entityId  = BitConverter.GetBytes(b.EntityId);
                    byte[] value     = BitConverter.GetBytes(id);

                    for (int i = 0; i < 4; i++)
                    {
                        message[i] = messageId[i];
                    }

                    for (int i = 0; i < 8; i++)
                    {
                        message[i + 4] = entityId[i];
                    }

                    for (int i = 0; i < 4; i++)
                    {
                        message[i + 12] = value[i];
                    }

                    MyAPIGateway.Multiplayer.SendMessageToOthers(5910, message, true);
                }
            };

            MyAPIGateway.TerminalControls.AddControl <Sandbox.ModAPI.Ingame.IMyRefinery>(m_controlId);


            // power field
            m_controlPower         = MyAPIGateway.TerminalControls.CreateControl <IMyTerminalControlTextbox, Sandbox.ModAPI.Ingame.IMyRefinery>("Cython.OPT.Power");
            m_controlPower.Enabled = (b) => b.GameLogic.GetAs <OpticalPowerTransmitter>().m_sender;
            m_controlPower.Visible = (b) => b.BlockDefinition.SubtypeId.Equals("LargeBlockSmallOpticalPowerTransmitter") || b.BlockDefinition.SubtypeId.Equals("SmallBlockSmallOpticalPowerTransmitter");
            m_controlPower.Title   = MyStringId.GetOrCompute("Power");
            m_controlPower.Tooltip = MyStringId.GetOrCompute("Maximum power this transmitter is supposed to send.");
            m_controlPower.Getter  = (b) => (new StringBuilder()).Append(b.GameLogic.GetAs <OpticalPowerTransmitter>().m_transmittedPower);
            m_controlPower.Setter  = (b, s) => {
                float power;

                if (float.TryParse(s.ToString(), out power))
                {
                    var OPT = b.GameLogic.GetAs <OpticalPowerTransmitter>();

                    OPT.m_transmittedPower = power;

                    if (OPT.m_transmittedPower > OPT.m_currentMaxPower)
                    {
                        OPT.m_transmittedPower = OPT.m_currentMaxPower;
                    }

                    byte[] message   = new byte[16];
                    byte[] messageId = BitConverter.GetBytes(5);
                    byte[] entityId  = BitConverter.GetBytes(b.EntityId);
                    byte[] value     = BitConverter.GetBytes(OPT.m_transmittedPower);

                    for (int i = 0; i < 4; i++)
                    {
                        message[i] = messageId[i];
                    }

                    for (int i = 0; i < 8; i++)
                    {
                        message[i + 4] = entityId[i];
                    }

                    for (int i = 0; i < 4; i++)
                    {
                        message[i + 12] = value[i];
                    }

                    MyAPIGateway.Multiplayer.SendMessageToOthers(5910, message, true);
                }
            };

            MyAPIGateway.TerminalControls.AddControl <IMyRefinery>(m_controlPower);
        }
        // Context: All
        public override void UpdateOnceBeforeFrame()
        {
            if (me.CubeGrid?.Physics == null)
            {
                return;
            }

            _state = new SyncableProjectorState(me, State.Idle, 0);

            if (Constants.IsServer)
            {
                LoadStorage();
                _settings.OnValueReceived += SaveStorage;
                BuildState           = State.Idle;
                me.IsWorkingChanged += Me_IsWorkingChanged;
            }
            else
            {
                _settings = new SyncableProjectorSettings(me, 0, true);
                _state.RequestFromServer();
                _settings.RequestFromServer();
                _state.OnValueReceived += ReceivedNewState;
            }

            MyProjectorDefinition def = (MyProjectorDefinition)MyDefinitionManager.Static.GetCubeBlockDefinition(me.BlockDefinition);

            minPower = def.RequiredPowerInput;
            sink     = me.Components.Get <MyResourceSinkComponent>();
            MyDefinitionId powerDef = MyResourceDistributorComponent.ElectricityId;

            sink.SetRequiredInputFuncByType(powerDef, GetCurrentPower);
            sink.Update();
            _settings.OnValueReceived += RefreshUI;

            me.AppendingCustomInfo += CustomInfo;
            me.RefreshCustomInfo();

            Settings.MapSettings config = IPSession.Instance.MapSettings;
            config.OnSubgridsChanged += ClearCachedComps;
            config.OnComponentCostModifierChanged += ClearCachedComps;
            config.OnExtraComponentChanged        += ClearCachedComps;
            config.OnExtraCompCostChanged         += ClearCachedComps;

            if (!controls)
            {
                // Terminal controls

                IMyTerminalControlSeparator sep = MyAPIGateway.TerminalControls.CreateControl <IMyTerminalControlSeparator, IMyProjector>("BuildGridSep");
                sep.Enabled = IsValid;
                sep.Visible = IsValid;
                MyAPIGateway.TerminalControls.AddControl <IMyProjector>(sep);

                IMyTerminalControlButton btnBuild = MyAPIGateway.TerminalControls.CreateControl <IMyTerminalControlButton, IMyProjector>("BuildGrid");
                btnBuild.Enabled = IsWorking;
                btnBuild.Visible = IsValid;
                btnBuild.SupportsMultipleBlocks = true;
                btnBuild.Title   = MyStringId.GetOrCompute("Build Grid");
                btnBuild.Action  = BuildClient;
                btnBuild.Tooltip = MyStringId.GetOrCompute("Builds the projection instantly.\nThere will be a cooldown after building.");
                MyAPIGateway.TerminalControls.AddControl <IMyProjector>(btnBuild);

                IMyTerminalControlButton btnCancel = MyAPIGateway.TerminalControls.CreateControl <IMyTerminalControlButton, IMyProjector>("CancelBuildGrid");
                btnCancel.Enabled = IsWorking;
                btnCancel.Visible = IsValid;
                btnCancel.SupportsMultipleBlocks = true;
                btnCancel.Title   = MyStringId.GetOrCompute("Cancel");
                btnCancel.Action  = CancelClient;
                btnCancel.Tooltip = MyStringId.GetOrCompute("Cancels the build process.");
                MyAPIGateway.TerminalControls.AddControl <IMyProjector>(btnCancel);

                IMyTerminalControlCheckbox chkShift = MyAPIGateway.TerminalControls.CreateControl <IMyTerminalControlCheckbox, IMyProjector>("MoveProjectionArea");
                chkShift.Enabled = IsWorking;
                chkShift.Visible = IsValid;
                chkShift.SupportsMultipleBlocks = true;
                chkShift.Title   = MyStringId.GetOrCompute("Loose Projection Area");
                chkShift.OnText  = MyStringId.GetOrCompute("On");
                chkShift.OffText = MyStringId.GetOrCompute("Off");
                chkShift.Tooltip = MyStringId.GetOrCompute("Allow the projection to spawn in a different area if the original area is occupied.");
                chkShift.Setter  = SetLooseArea;
                chkShift.Getter  = GetLooseArea;
                MyAPIGateway.TerminalControls.AddControl <IMyProjector>(chkShift);

                IMyTerminalControlSlider sliderSpeed = MyAPIGateway.TerminalControls.CreateControl <IMyTerminalControlSlider, IMyProjector>("BuildSpeed");
                sliderSpeed.Enabled = IsWorking;
                sliderSpeed.Visible = IsValid;
                sliderSpeed.SupportsMultipleBlocks = true;
                sliderSpeed.Title   = MyStringId.GetOrCompute("Speed");
                sliderSpeed.Tooltip = MyStringId.GetOrCompute("Increasing the speed will use more energy.");
                sliderSpeed.SetLogLimits(Constants.minSpeed, Constants.maxSpeed);
                sliderSpeed.Writer = GetSpeedText;
                sliderSpeed.Getter = GetSpeed;
                sliderSpeed.Setter = SetSpeed;
                MyAPIGateway.TerminalControls.AddControl <IMyProjector>(sliderSpeed);

                IMyTerminalControlTextbox txtTimeout = MyAPIGateway.TerminalControls.CreateControl <IMyTerminalControlTextbox, IMyProjector>("GridTimer");
                txtTimeout.Enabled = (b) => false;
                txtTimeout.Visible = IsValid;
                txtTimeout.Getter  = GetTimer;
                txtTimeout.Setter  = (b, s) => { };
                txtTimeout.SupportsMultipleBlocks = false;
                txtTimeout.Title   = MyStringId.GetOrCompute("Build Timer");
                txtTimeout.Tooltip = MyStringId.GetOrCompute("The amount of time you must wait after building a grid to be able to build another.");
                MyAPIGateway.TerminalControls.AddControl <IMyProjector>(txtTimeout);

                // Terminal actions
                // Button panels are special and trigger on the server instead of the client, making everything more complicated.

                IMyTerminalAction aCancel = MyAPIGateway.TerminalControls.CreateAction <IMyProjector>("CancelBuildAction");
                aCancel.Enabled             = IsValid;
                aCancel.Action              = CancelClient; // For all except button panels
                aCancel.ValidForGroups      = true;
                aCancel.Name                = new StringBuilder("Cancel Spawn Grid");
                aCancel.Writer              = (b, s) => s.Append("Cancel");
                aCancel.InvalidToolbarTypes = new[] { MyToolbarType.ButtonPanel }.ToList();
                MyAPIGateway.TerminalControls.AddAction <IMyProjector>(aCancel);
                IMyTerminalAction aCancel2 = MyAPIGateway.TerminalControls.CreateAction <IMyProjector>("CancelBuildGrid");
                aCancel2.Enabled             = IsValid;
                aCancel2.Action              = CancelClientUnsafe; // For only button panels
                aCancel2.ValidForGroups      = true;
                aCancel2.Name                = new StringBuilder("Cancel Spawn Grid");
                aCancel2.Writer              = (b, s) => s.Append("Cancel");
                aCancel2.InvalidToolbarTypes = new List <MyToolbarType> {
                    MyToolbarType.BuildCockpit, MyToolbarType.Character, MyToolbarType.LargeCockpit,
                    MyToolbarType.None, MyToolbarType.Seat, MyToolbarType.Ship, MyToolbarType.SmallCockpit, MyToolbarType.Spectator
                };
                MyAPIGateway.TerminalControls.AddAction <IMyProjector>(aCancel2);

                IMyTerminalAction aBuild = MyAPIGateway.TerminalControls.CreateAction <IMyProjector>("BuildGridAction");
                aBuild.Enabled             = IsValid;
                aBuild.Action              = BuildClient; // For all except button panels
                aBuild.ValidForGroups      = true;
                aBuild.Name                = new StringBuilder("Spawn Grid");
                aBuild.Writer              = (b, s) => s.Append("Spawn");
                aBuild.InvalidToolbarTypes = new [] { MyToolbarType.ButtonPanel }.ToList();
                MyAPIGateway.TerminalControls.AddAction <IMyProjector>(aBuild);
                IMyTerminalAction aBuild2 = MyAPIGateway.TerminalControls.CreateAction <IMyProjector>("BuildGrid");
                aBuild2.Enabled             = IsValid;
                aBuild2.Action              = BuildClientUnsafe; // For only button panels
                aBuild2.ValidForGroups      = true;
                aBuild2.Name                = new StringBuilder("Spawn Grid");
                aBuild2.Writer              = (b, s) => s.Append("Spawn");
                aBuild2.InvalidToolbarTypes = new List <MyToolbarType> {
                    MyToolbarType.BuildCockpit, MyToolbarType.Character, MyToolbarType.LargeCockpit,
                    MyToolbarType.None, MyToolbarType.Seat, MyToolbarType.Ship, MyToolbarType.SmallCockpit, MyToolbarType.Spectator
                };
                MyAPIGateway.TerminalControls.AddAction <IMyProjector>(aBuild2);

                IMyTerminalControlListbox itemList = MyAPIGateway.TerminalControls.CreateControl <IMyTerminalControlListbox, IMyProjector>("ComponentList");
                itemList.Enabled                = IsWorking;
                itemList.Visible                = IsValid;
                itemList.ListContent            = GetItemList;
                itemList.Multiselect            = false;
                itemList.SupportsMultipleBlocks = false;
                itemList.Title            = MyStringId.GetOrCompute("Components");
                itemList.VisibleRowsCount = 10;
                itemList.ItemSelected     = (b, l) => { };
                MyAPIGateway.TerminalControls.AddControl <IMyProjector>(itemList);


                // Programmable Block stuff

                IMyTerminalControlProperty <Dictionary <MyItemType, int> > itemListProp
                    = MyAPIGateway.TerminalControls.CreateProperty <Dictionary <MyItemType, int>, IMyProjector>("RequiredComponents");
                itemListProp.Enabled = IsWorking;
                itemListProp.Visible = IsValid;
                itemListProp.SupportsMultipleBlocks = false;
                itemListProp.Setter = (b, l) => { };
                itemListProp.Getter = GetItemListPB;
                MyAPIGateway.TerminalControls.AddControl <IMyProjector>(itemListProp);

                IMyTerminalControlProperty <int> gridTimeoutProp
                    = MyAPIGateway.TerminalControls.CreateProperty <int, IMyProjector>("GridTimerProjection");
                gridTimeoutProp.Enabled = IsWorking;
                gridTimeoutProp.Visible = IsValid;
                gridTimeoutProp.SupportsMultipleBlocks = false;
                gridTimeoutProp.Setter = (b, l) => { };
                gridTimeoutProp.Getter = GetMaxTimerPB;
                MyAPIGateway.TerminalControls.AddControl <IMyProjector>(gridTimeoutProp);

                IMyTerminalControlProperty <int> gridTimeoutActive
                    = MyAPIGateway.TerminalControls.CreateProperty <int, IMyProjector>("GridTimerCurrent");
                gridTimeoutActive.Enabled = IsWorking;
                gridTimeoutActive.Visible = IsValid;
                gridTimeoutActive.SupportsMultipleBlocks = false;
                gridTimeoutActive.Setter = (b, l) => { };
                gridTimeoutActive.Getter = GetCurrentTimerPB;
                MyAPIGateway.TerminalControls.AddControl <IMyProjector>(gridTimeoutActive);

                IMyTerminalControlProperty <int> buildState
                    = MyAPIGateway.TerminalControls.CreateProperty <int, IMyProjector>("BuildState");
                buildState.Enabled = IsWorking;
                buildState.Visible = IsValid;
                buildState.SupportsMultipleBlocks = false;
                buildState.Setter = (b, l) => { };
                buildState.Getter = GetStatePB;
                MyAPIGateway.TerminalControls.AddControl <IMyProjector>(gridTimeoutActive);

                MyLog.Default.WriteLineAndConsole("Initialized Instant Projector.");
                controls = true;
            }
        }
        public static void Create()
        {
            if (controls)
            {
                return;
            }

            IMyTerminalControlSeparator sep = MyAPIGateway.TerminalControls.CreateControl <IMyTerminalControlSeparator, IMyProjector>("BuildGridSep");

            sep.Enabled = IsValid;
            sep.Visible = IsValid;
            sep.SupportsMultipleBlocks = true;
            MyAPIGateway.TerminalControls.AddControl <IMyProjector>(sep);

            IMyTerminalControlLabel lbl = MyAPIGateway.TerminalControls.CreateControl <IMyTerminalControlLabel, IMyProjector>("BuildGridLabel");

            lbl.Enabled = IsValid;
            lbl.Visible = IsValid;
            lbl.SupportsMultipleBlocks = true;
            lbl.Label = MyStringId.GetOrCompute("Instant Projector Controls");
            MyAPIGateway.TerminalControls.AddControl <IMyProjector>(lbl);

            IMyTerminalControlButton btnBuild = MyAPIGateway.TerminalControls.CreateControl <IMyTerminalControlButton, IMyProjector>("BuildGrid");

            btnBuild.Enabled = IsWorking;
            btnBuild.Visible = IsValid;
            btnBuild.SupportsMultipleBlocks = true;
            btnBuild.Title   = MyStringId.GetOrCompute("Build Grid");
            btnBuild.Action  = BuildClient;
            btnBuild.Tooltip = MyStringId.GetOrCompute("Builds the projection instantly.\nThere will be a cooldown after building.");
            MyAPIGateway.TerminalControls.AddControl <IMyProjector>(btnBuild);

            IMyTerminalControlButton btnCancel = MyAPIGateway.TerminalControls.CreateControl <IMyTerminalControlButton, IMyProjector>("CancelBuildGrid");

            btnCancel.Enabled = IsWorking;
            btnCancel.Visible = IsValid;
            btnCancel.SupportsMultipleBlocks = true;
            btnCancel.Title   = MyStringId.GetOrCompute("Cancel");
            btnCancel.Action  = CancelClient;
            btnCancel.Tooltip = MyStringId.GetOrCompute("Cancels the build process.");
            MyAPIGateway.TerminalControls.AddControl <IMyProjector>(btnCancel);

            IMyTerminalControlCheckbox chkShift = MyAPIGateway.TerminalControls.CreateControl <IMyTerminalControlCheckbox, IMyProjector>("MoveProjectionArea");

            chkShift.Enabled = IsWorking;
            chkShift.Visible = IsValid;
            chkShift.SupportsMultipleBlocks = true;
            chkShift.Title   = MyStringId.GetOrCompute("Loose Projection Area");
            chkShift.OnText  = MyStringId.GetOrCompute("On");
            chkShift.OffText = MyStringId.GetOrCompute("Off");
            chkShift.Tooltip = MyStringId.GetOrCompute("Allow the projection to spawn in a different area if the original area is occupied.");
            chkShift.Setter  = SetLooseArea;
            chkShift.Getter  = GetLooseArea;
            MyAPIGateway.TerminalControls.AddControl <IMyProjector>(chkShift);

            IMyTerminalControlSlider sliderSpeed = MyAPIGateway.TerminalControls.CreateControl <IMyTerminalControlSlider, IMyProjector>("BuildSpeed");

            sliderSpeed.Enabled = IsWorking;
            sliderSpeed.Visible = IsValid;
            sliderSpeed.SupportsMultipleBlocks = true;
            sliderSpeed.Title   = MyStringId.GetOrCompute("Speed");
            sliderSpeed.Tooltip = MyStringId.GetOrCompute("Increasing the speed will use more energy.");
            sliderSpeed.SetLogLimits(Constants.minSpeed, Constants.maxSpeed);
            sliderSpeed.Writer = GetSpeedText;
            sliderSpeed.Getter = GetSpeed;
            sliderSpeed.Setter = SetSpeed;
            MyAPIGateway.TerminalControls.AddControl <IMyProjector>(sliderSpeed);

            IMyTerminalControlTextbox txtTimeout = MyAPIGateway.TerminalControls.CreateControl <IMyTerminalControlTextbox, IMyProjector>("GridTimer");

            txtTimeout.Enabled = (b) => false;
            txtTimeout.Visible = IsValid;
            txtTimeout.Getter  = GetTimer;
            txtTimeout.Setter  = (b, s) => { };
            txtTimeout.SupportsMultipleBlocks = false;
            txtTimeout.Title   = MyStringId.GetOrCompute("Build Timer");
            txtTimeout.Tooltip = MyStringId.GetOrCompute("The amount of time you must wait after building a grid to be able to build another.");
            MyAPIGateway.TerminalControls.AddControl <IMyProjector>(txtTimeout);

            // Terminal actions
            // Button panels are special and trigger on the server instead of the client, making everything more complicated.

            IMyTerminalAction aCancel = MyAPIGateway.TerminalControls.CreateAction <IMyProjector>("CancelBuildAction");

            aCancel.Enabled             = IsValid;
            aCancel.Action              = CancelClient; // For all except button panels
            aCancel.ValidForGroups      = true;
            aCancel.Name                = new StringBuilder("Cancel Spawn Grid");
            aCancel.Writer              = (b, s) => s.Append("Cancel");
            aCancel.InvalidToolbarTypes = new[] { MyToolbarType.ButtonPanel }.ToList();
            MyAPIGateway.TerminalControls.AddAction <IMyProjector>(aCancel);
            IMyTerminalAction aCancel2 = MyAPIGateway.TerminalControls.CreateAction <IMyProjector>("CancelBuildGrid");

            aCancel2.Enabled             = IsValid;
            aCancel2.Action              = CancelClientUnsafe; // For only button panels
            aCancel2.ValidForGroups      = true;
            aCancel2.Name                = new StringBuilder("Cancel Spawn Grid");
            aCancel2.Writer              = (b, s) => s.Append("Cancel");
            aCancel2.InvalidToolbarTypes = new List <MyToolbarType> {
                MyToolbarType.BuildCockpit, MyToolbarType.Character, MyToolbarType.LargeCockpit,
                MyToolbarType.None, MyToolbarType.Seat, MyToolbarType.Ship, MyToolbarType.SmallCockpit, MyToolbarType.Spectator
            };
            MyAPIGateway.TerminalControls.AddAction <IMyProjector>(aCancel2);

            IMyTerminalAction aBuild = MyAPIGateway.TerminalControls.CreateAction <IMyProjector>("BuildGridAction");

            aBuild.Enabled             = IsValid;
            aBuild.Action              = BuildClient; // For all except button panels
            aBuild.ValidForGroups      = true;
            aBuild.Name                = new StringBuilder("Spawn Grid");
            aBuild.Writer              = (b, s) => s.Append("Spawn");
            aBuild.InvalidToolbarTypes = new[] { MyToolbarType.ButtonPanel }.ToList();
            MyAPIGateway.TerminalControls.AddAction <IMyProjector>(aBuild);
            IMyTerminalAction aBuild2 = MyAPIGateway.TerminalControls.CreateAction <IMyProjector>("BuildGrid");

            aBuild2.Enabled             = IsValid;
            aBuild2.Action              = BuildClientUnsafe; // For only button panels
            aBuild2.ValidForGroups      = true;
            aBuild2.Name                = new StringBuilder("Spawn Grid");
            aBuild2.Writer              = (b, s) => s.Append("Spawn");
            aBuild2.InvalidToolbarTypes = new List <MyToolbarType> {
                MyToolbarType.BuildCockpit, MyToolbarType.Character, MyToolbarType.LargeCockpit,
                MyToolbarType.None, MyToolbarType.Seat, MyToolbarType.Ship, MyToolbarType.SmallCockpit, MyToolbarType.Spectator
            };
            MyAPIGateway.TerminalControls.AddAction <IMyProjector>(aBuild2);

            IMyTerminalControlListbox itemList = MyAPIGateway.TerminalControls.CreateControl <IMyTerminalControlListbox, IMyProjector>("ComponentList");

            itemList.Enabled                = IsWorking;
            itemList.Visible                = IsValid;
            itemList.ListContent            = GetItemList;
            itemList.Multiselect            = false;
            itemList.SupportsMultipleBlocks = false;
            itemList.Title            = MyStringId.GetOrCompute("Components");
            itemList.VisibleRowsCount = 10;
            itemList.ItemSelected     = (b, l) => { };
            MyAPIGateway.TerminalControls.AddControl <IMyProjector>(itemList);

            IMyTerminalControlButton itemListInfo = MyAPIGateway.TerminalControls.CreateControl <IMyTerminalControlButton, IMyProjector>("ComponentListInfo");

            itemListInfo.Enabled = IsWorking;
            itemListInfo.Visible = IsValid;
            itemListInfo.SupportsMultipleBlocks = false;
            itemListInfo.Title  = MyStringId.GetOrCompute("Check Inventory");
            itemListInfo.Action = OpenItemList;
            MyAPIGateway.TerminalControls.AddControl <IMyProjector>(itemListInfo);


            // Programmable Block stuff

            IMyTerminalControlProperty <Dictionary <MyItemType, int> > itemListProp
                = MyAPIGateway.TerminalControls.CreateProperty <Dictionary <MyItemType, int>, IMyProjector>("RequiredComponents");

            itemListProp.Enabled = IsWorking;
            itemListProp.Visible = IsValid;
            itemListProp.SupportsMultipleBlocks = false;
            itemListProp.Setter = (b, l) => { };
            itemListProp.Getter = GetItemListPB;
            MyAPIGateway.TerminalControls.AddControl <IMyProjector>(itemListProp);

            IMyTerminalControlProperty <int> gridTimeoutProp
                = MyAPIGateway.TerminalControls.CreateProperty <int, IMyProjector>("GridTimerProjection");

            gridTimeoutProp.Enabled = IsWorking;
            gridTimeoutProp.Visible = IsValid;
            gridTimeoutProp.SupportsMultipleBlocks = false;
            gridTimeoutProp.Setter = (b, l) => { };
            gridTimeoutProp.Getter = GetMaxTimerPB;
            MyAPIGateway.TerminalControls.AddControl <IMyProjector>(gridTimeoutProp);

            IMyTerminalControlProperty <int> gridTimeoutActive
                = MyAPIGateway.TerminalControls.CreateProperty <int, IMyProjector>("GridTimerCurrent");

            gridTimeoutActive.Enabled = IsWorking;
            gridTimeoutActive.Visible = IsValid;
            gridTimeoutActive.SupportsMultipleBlocks = false;
            gridTimeoutActive.Setter = (b, l) => { };
            gridTimeoutActive.Getter = GetCurrentTimerPB;
            MyAPIGateway.TerminalControls.AddControl <IMyProjector>(gridTimeoutActive);

            IMyTerminalControlProperty <int> buildState
                = MyAPIGateway.TerminalControls.CreateProperty <int, IMyProjector>("BuildState");

            buildState.Enabled = IsWorking;
            buildState.Visible = IsValid;
            buildState.SupportsMultipleBlocks = false;
            buildState.Setter = (b, l) => { };
            buildState.Getter = GetStatePB;
            MyAPIGateway.TerminalControls.AddControl <IMyProjector>(gridTimeoutActive);

            MyLog.Default.WriteLineAndConsole("Initialized Instant Projector.");
            controls = true;
        }