Example #1
0
        private static void ReceiveMissilePositions(byte[] data, int pos)
        {
            if (MyAPIGateway.Multiplayer.IsServer)
            {
                return;
            }

            int index    = Static.AllGuidedMissiles.Count - 1;
            bool updated = false;

            while (pos < data.Length)
            {
                Vector3D worldPos = ByteConverter.GetVector3D(data, ref pos);
                Vector3 velocity  = ByteConverter.GetVector3(data, ref pos);

                while (true)
                {
                    if (index < 0)
                    {
                        if (!updated)
                        {
                            // it could be that server only has missiles that were generated before the client connects and client only has missiles that were generated after server sent message
                            Logger.AlwaysLog("Failed to update missile positions. Local count: " + Static.AllGuidedMissiles.Count + ", bytes received: " + data.Length, Logger.severity.INFO);
                        }
                        else
                        {
                            // normal when client connects while missiles are in play
                            Logger.DebugLog("Server has more missiles than client. Local count: " + Static.AllGuidedMissiles.Count + ", bytes received: " + data.Length, Logger.severity.INFO);
                        }
                        return;
                    }

                    GuidedMissile missile = Static.AllGuidedMissiles[index--];

                    // it is possible that the client has extra missiles
                    Vector3D currentPosition = missile.MyEntity.PositionComp.GetPosition();
                    if (Vector3D.DistanceSquared(worldPos, currentPosition) > 100d)
                    {
                        if (updated)
                        {
                            Logger.AlwaysLog("Interruption in missile position updates, it is likely that threshold needs to be adjusted. " +
                                             "Local count: " + Static.AllGuidedMissiles.Count + ", bytes received: " + data.Length + ", distance squared: " + Vector3D.DistanceSquared(worldPos, currentPosition), Logger.severity.WARNING);
                        }
                        else
                        {
                            Logger.DebugLog("Position values are far apart, trying next missile");
                        }
                        continue;
                    }

                    updated = true;
                    Logger.DebugLog("Update position of " + missile.MyEntity.EntityId + " from " + missile.MyEntity.PositionComp.GetPosition() + " to " + worldPos);
                    missile.MyEntity.SetPosition(worldPos);
                    missile.MyEntity.Physics.LinearVelocity = velocity;
                    break;
                }
            }
        }
        private void StartCooldown()
        {
            if (clusterMain != null)
                clusterMain.MyEntity.OnClose -= ClusterMain_OnClose;

            clusterMain = null;
            FuncBlock.RequestEnable(false);
            FuncBlock.ApplyAction("Shoot_Off");
            onCooldown = true;
            cooldownUntil = DateTime.UtcNow + TimeSpan.FromSeconds(loadedAmmo.Description.ClusterCooldown);
        }
Example #3
0
        public static void Update100()
        {
#if PROFILE
            Profiler.StartProfileBlock();
            try
            {
#endif

            if (Static.AllGuidedMissiles.Count == 0)
            {
                return;
            }

            if (MyAPIGateway.Multiplayer.IsServer)
            {
                if (Static.SerialPositions == null)
                {
                    Static.SerialPositions = new List <byte>();
                }
                else
                {
                    Static.SerialPositions.Clear();
                }
                ByteConverter.AppendBytes(Static.SerialPositions, MessageHandler.SubMod.GuidedMissile);
            }

            for (int index = Static.AllGuidedMissiles.Count - 1; index >= 0; index--)
            {
                GuidedMissile missile = Static.AllGuidedMissiles[index];

                try
                {
                    if (!missile.Stopped)
                    {
                        missile.ClearBlacklist();
                        if (missile.m_gravData != null)
                        {
                            missile.UpdateGravity();
                        }
                    }
                    if (!missile.Stopped)
                    {
                        missile.UpdateNetwork();
                    }

                    if (MyAPIGateway.Multiplayer.IsServer && Static.SerialPositions.Count < 4000)                     // message fails at 4096
                    {
                        ByteConverter.AppendBytes(Static.SerialPositions, missile.MyEntity.PositionComp.GetPosition());
                        ByteConverter.AppendBytes(Static.SerialPositions, missile.MyEntity.Physics.LinearVelocity);
                    }
                }
                catch (Exception ex)
                {
                    Logger.AlwaysLog("Exception with missile: " + missile.MyEntity + ":\n" + ex);
                    Static.AllGuidedMissiles.Remove(missile);
                }
            }

            if (MyAPIGateway.Multiplayer.IsServer)
            {
                if (!MyAPIGateway.Multiplayer.SendMessageToOthers(MessageHandler.ModId, Static.SerialPositions.ToArray(), false))
                {
                    Logger.AlwaysLog("Missile sync failed, too many missiles in play: " + Static.AllGuidedMissiles.Count + ", byte count: " + Static.SerialPositions.Count);
                }
            }

#if PROFILE
        }

        finally
        {
            Profiler.EndProfileBlock();
        }
#endif
        }
        private bool MissileBelongsTo(IMyEntity missile)
        {
            if (!(CubeBlock as Ingame.IMyUserControllableGun).IsShooting)
            {
                myLogger.debugLog("Not mine, not shooting", "MissileBelongsTo()");
                return false;
            }
            Vector3D local = Vector3D.Transform(missile.GetPosition(), CubeBlock.WorldMatrixNormalizedInv);
            if (MissileSpawnBox.Contains(local) != ContainmentType.Contains)
            {
                myLogger.debugLog("Not in my box: " + missile + ", position: " + local, "MissileBelongsTo()");
                return false;
            }
            if (Vector3D.RectangularDistance(CubeBlock.WorldMatrix.Forward, missile.WorldMatrix.Forward) > 0.01)
            {
                myLogger.debugLog("Facing the wrong way: " + missile + ", RectangularDistance: " + Vector3D.RectangularDistance(CubeBlock.WorldMatrix.Forward, missile.WorldMatrix.Forward), "MissileBelongsTo()");
                return false;
            }

            if (loadedAmmo == null)
            {
                myLogger.debugLog("Mine but no loaded ammo!", "MissileBelongsTo()", Logger.severity.INFO);
                return true;
            }

            if (loadedAmmo.Description == null || loadedAmmo.Description.GuidanceSeconds < 1f)
            {
                myLogger.debugLog("Mine but not a guided missile!", "MissileBelongsTo()", Logger.severity.INFO);
                return true;
            }

            myLogger.debugLog("Opts: " + myFixed.Options, "MissileBelongsTo()");
            try
            {
                if (clusterMain != null)
                {
                    if (loadedAmmo.IsCluster)
                    {
                        if (clusterMain.AddToCluster(missile))
                        {
                            myLogger.debugLog("reached max cluster, on cooldown", "MissileBelongsTo()", Logger.severity.DEBUG);
                            StartCooldown();
                        }
                    }
                    else
                    {
                        myLogger.alwaysLog("deleting extraneous missile: " + missile, "MissileBelongsTo()", Logger.severity.WARNING);
                        missile.Delete();
                    }
                    return true;
                }

                LastSeen initialTarget = null;
                if (findAntenna())
                {
                    if (myFixed.Options.TargetEntityId.HasValue)
                        myAntenna.tryGetLastSeen(myFixed.Options.TargetEntityId.Value, out initialTarget);
                    else
                    {
                        myLogger.debugLog("Searching for target", "MissileBelongsTo()", Logger.severity.DEBUG);
                        float closestDistanceSquared = float.MaxValue;
                        myAntenna.ForEachLastSeen(seen => {
                            if (!seen.isRecent())
                                return false;
                            IMyCubeGrid grid = seen.Entity as IMyCubeGrid;
                            if (grid != null && CubeBlock.canConsiderHostile(grid) && myFixed.Options.CanTargetType(grid))
                            {
                                float distSquared = Vector3.DistanceSquared(CubeBlock.GetPosition(), grid.GetCentre());
                                if (distSquared < closestDistanceSquared)
                                {
                                    closestDistanceSquared = distSquared;
                                    initialTarget = seen;
                                }
                            }
                            return false;
                        });
                    }
                }

                myLogger.debugLog("creating new guided missile", "MissileBelongsTo()");
                GuidedMissile gm = new GuidedMissile(missile as MyAmmoBase, CubeBlock, myFixed.Options.Clone(), loadedAmmo, initialTarget);
                if (loadedAmmo.IsCluster)
                {
                    myLogger.debugLog("missile is a cluster missile", "MissileBelongsTo()");
                    clusterMain = gm;
                    missile.OnClose += ClusterMain_OnClose;
                    var builder = CubeBlock.GetObjectBuilder_Safe() as MyObjectBuilder_UserControllableGun ;
                    restoreShootingToggle = builder.IsShootingFromTerminal;
                    FuncBlock.ApplyAction("Shoot_On");
                }
            }
            catch (Exception ex)
            {
                myLogger.alwaysLog("failed to create GuidedMissile", "MissileBelongsTo()", Logger.severity.ERROR);
                myLogger.alwaysLog("Exception: " + ex, "MissileBelongsTo()",  Logger.severity.ERROR);
            }

            return true;
        }