protected void SendForwardShieldProjectors(ref int idx)
        {
            var data = Screen.GetEntities <ShieldProjectorCannon>().ToList();

            if (data.Count == 0)
            {
                return;
            }

            if (idx + 2 >= MAX_PACKAGE_SIZE_BYTES)
            {
                SendAndReset(ref idx);
            }

            MSG_FORWARD[idx] = AREA_SHIELDPROJECTORS;
            idx++;

            byte arrsize = (byte)((MAX_PACKAGE_SIZE_BYTES - idx - 2) / PLEN_SHIELDPROJECTOR);

            int posSize = idx;

            MSG_FORWARD[posSize] = 0xFF;
            idx++;

            int i = 0;

            foreach (var cannon in data)
            {
                if (!ShouldSendData(cannon))
                {
                    continue;
                }

                // [8: ID] [3: Fraction] [5: Boost] [32: RotationActual] [32: RotationTarget] [8: Health] [8:ChargeTime]

                NetworkDataTools.SetByte(out MSG_FORWARD[idx + 0], cannon.BlueprintCannonID);
                NetworkDataTools.SetSplitByte(out MSG_FORWARD[idx + 1], Screen.GetFractionID(cannon.Fraction), cannon.IntegerBoost, 3, 5, 3, 5);
                NetworkDataTools.SetSingle(out MSG_FORWARD[idx + 2], out MSG_FORWARD[idx + 3], out MSG_FORWARD[idx + 4], out MSG_FORWARD[idx + 5], cannon.Rotation.ActualValue);
                NetworkDataTools.SetSingle(out MSG_FORWARD[idx + 6], out MSG_FORWARD[idx + 7], out MSG_FORWARD[idx + 8], out MSG_FORWARD[idx + 9], cannon.Rotation.TargetValue);
                NetworkDataTools.SetByteFloor(out MSG_FORWARD[idx + 10], FloatMath.Clamp(cannon.CannonHealth.TargetValue, 0f, 1f) * 255);
                NetworkDataTools.SetByteFloor(out MSG_FORWARD[idx + 11], FloatMath.Clamp(cannon.ChargeTime / Cannon.SHIELDLASER_CHARGE_COOLDOWN_MAX, 0f, 1f) * 255);

                idx += PLEN_LASERCANNON;

                i++;
                if (i >= arrsize)
                {
                    MSG_FORWARD[posSize] = (byte)i;
                    SendAndReset(ref idx);
                    MSG_FORWARD[idx] = AREA_SHIELDPROJECTORS;
                    idx++;
                    i      -= arrsize;
                    arrsize = (byte)((MAX_PACKAGE_SIZE_BYTES - idx - 2) / PLEN_SHIELDPROJECTOR);
                    posSize = idx;
                    MSG_FORWARD[posSize] = 0xFF;
                    idx++;
                }
            }
            MSG_FORWARD[posSize] = (byte)i;
        }
        protected void SendForwardRelayCannons(ref int idx)
        {
            var data = Screen.GetEntities <RelayCannon>().ToList();

            if (data.Count == 0)
            {
                return;
            }

            if (idx + 2 >= MAX_PACKAGE_SIZE_BYTES)
            {
                SendAndReset(ref idx);
            }

            MSG_FORWARD[idx] = AREA_BULLETCANNONS;
            idx++;

            byte arrsize = (byte)((MAX_PACKAGE_SIZE_BYTES - idx - 2) / PLEN_RELAYCANNON);

            int posSize = idx;

            MSG_FORWARD[posSize] = 0xFF;
            idx++;

            int i = 0;

            foreach (var cannon in data)
            {
                if (!ShouldSendData(cannon))
                {
                    continue;
                }

                // [8: ID] [3: Fraction] [5: Boost] [8: RotationActual] [8: RotationTarget] [8:Shield]

                NetworkDataTools.SetByte(out MSG_FORWARD[idx + 0], cannon.BlueprintCannonID);
                NetworkDataTools.SetSplitByte(out MSG_FORWARD[idx + 1], Screen.GetFractionID(cannon.Fraction), cannon.IntegerBoost, 3, 5, 3, 5);
                NetworkDataTools.SetByte(out MSG_FORWARD[idx + 2], NetworkDataTools.ConvertFromRadians(cannon.Rotation.ActualValue, 8));
                NetworkDataTools.SetByte(out MSG_FORWARD[idx + 3], NetworkDataTools.ConvertFromRadians(cannon.Rotation.TargetValue, 8));
                NetworkDataTools.SetByteFloorRange(out MSG_FORWARD[idx + 4], 0, Cannon.MAX_SHIELD_TIME, cannon.ShieldTime);

                idx += PLEN_RELAYCANNON;

                i++;
                if (i >= arrsize)
                {
                    MSG_FORWARD[posSize] = (byte)i;
                    SendAndReset(ref idx);
                    MSG_FORWARD[idx] = AREA_RELAYCANNONS;
                    idx++;
                    i      -= arrsize;
                    arrsize = (byte)((MAX_PACKAGE_SIZE_BYTES - idx - 2) / PLEN_RELAYCANNON);
                    posSize = idx;
                    MSG_FORWARD[posSize] = 0xFF;
                    idx++;
                }
            }
            MSG_FORWARD[posSize] = (byte)i;
        }