コード例 #1
0
        private void QueryTrigger()
        {
            m_queryResult.Clear();
            MyGamePruningStructure.GetTopMostEntitiesInBox(ref m_triggerAABB, m_queryResult);
            for (int i = m_queryResult.Count - 1; i >= 0; i--)
            {
                var e = m_queryResult[i];
                if (e.Physics == null || e.Physics.IsStatic)
                {
                    m_queryResult.RemoveAtFast(i);
                    continue;
                }

                if (e is MyFloatingObject || e is MyDebrisBase)
                {
                    m_queryResult.RemoveAtFast(i);
                    continue;
                }

                if (e == Entity.GetTopMostParent())
                {
                    m_queryResult.RemoveAtFast(i);
                    continue;
                }
                //if (e.Physics.RigidBody != null && e.Physics.RigidBody.IsActive)
                //    activeCounter++;
                //e.Physics.RigidBody.Activated += RBActivated;
                //e.Physics.RigidBody.Deactivated += RBDeactivated;
            }
        }
コード例 #2
0
        private List <MyEntity> EntitiesInLargeAABB(BoundingBoxD start, BoundingBoxD end)
        {
            Vector3D[] pathPoints = new Vector3D[4];
            pathPoints[0] = start.Min;
            pathPoints[1] = start.Max;
            pathPoints[2] = end.Min;
            pathPoints[3] = end.Max;
            BoundingBoxD PathAABB = BoundingBoxD.CreateFromPoints(pathPoints);

            //m_logger.debugLog("Path AABB = " + PathAABB, "EntitiesInLargeAABB()");

            m_offenders.Clear();
            MyGamePruningStructure.GetTopMostEntitiesInBox(ref PathAABB, m_offenders);
            m_offRemove.Clear();
            for (int i = 0; i < m_offenders.Count; i++)
            {
                if (!collect_Entity(m_grid, m_offenders[i]) ||
                    (m_ignoreEntity != null && m_ignoreEntity == m_offenders[i]))
                {
                    //m_logger.debugLog("discarding: " + m_offenders[i].getBestName(), "EntitiesInLargeAABB()");
                    m_offRemove.Add(m_offenders[i]);
                }
            }
            for (int i = 0; i < m_offRemove.Count; i++)
            {
                m_offenders.Remove(m_offRemove[i]);
            }

            return(m_offenders);
        }
コード例 #3
0
        public override void UpdateAfterSimulation()
        {
            if (Tick % 5 == 0)
            {
                if (Camera == null)
                {
                    return;
                }
                rainImpactEntities.Clear();

                MyGamePruningStructure.GetTopMostEntitiesInBox(ref frustumBBox, rainImpactEntities);
                //MyAPIGateway.Parallel.Start(CalculateLines);
                CalculateLines();
            }

            if (Tick % 60 == 0 && closestPlanet != null)
            {
                cameraDistanceFromSurface = closestPlanet.GetClosestSurfacePointGlobal(Camera.Position);
                cameraAltitude            = (Camera.Position - cameraDistanceFromSurface).Length();
            }

            if (Tick % 301 == 0)
            {
                closestPlanet = MyGamePruningStructure.GetClosestPlanet(Camera.Position);
                if (closestPlanet != null)
                {
                    planetCentre = closestPlanet.PositionComp.WorldAABB.Center;
                }
            }

            lines.Clear();
        }
コード例 #4
0
        public override IMyReplicable GetDependency()
        {
            if (m_physicsSync == null || Grid.IsStatic)
            {
                return(null);
            }

            MyCubeGrid master = MyGridPhysicsStateGroup.GetMasterGrid(Grid);

            if (master != Grid)
            {
                return(MyExternalReplicable.FindByObject(master));
            }

            BoundingBoxD box   = Grid.PositionComp.WorldAABB;
            var          group = MyCubeGridGroups.Static.PhysicalDynamic.GetGroup(Grid);

            if (group != null)
            {
                foreach (var node in group.Nodes)
                {
                    box.Include(node.NodeData.PositionComp.WorldAABB);
                }
            }

            if (m_foundEntities == null)
            {
                m_foundEntities = new List <MyEntity>();
            }

            m_foundEntities.Clear();

            MyGamePruningStructure.GetTopMostEntitiesInBox(ref box, m_foundEntities);

            float      maxRadius   = 0;
            MyCubeGrid biggestGrid = null;

            foreach (var entity in m_foundEntities)
            {
                MyCubeGrid grid = entity as MyCubeGrid;
                if (grid != null)
                {
                    var rad = grid.PositionComp.LocalVolume.Radius;
                    if (rad > maxRadius || (rad == maxRadius && (biggestGrid == null || grid.EntityId > biggestGrid.EntityId)))
                    {
                        maxRadius   = rad;
                        biggestGrid = grid;
                    }
                }
            }

            if (biggestGrid != null && biggestGrid != Grid)
            {
                return(MyExternalReplicable.FindByObject(biggestGrid));
            }

            return(null);
        }
コード例 #5
0
 protected virtual void UpdateInternal()
 {
     if (this.DoQuery)
     {
         this.m_queryResult.Clear();
         TriggerType triggerType = this.m_triggerType;
         if (triggerType == TriggerType.AABB)
         {
             MyGamePruningStructure.GetTopMostEntitiesInBox(ref this.m_AABB, this.m_queryResult, MyEntityQueryType.Both);
         }
         else
         {
             if (triggerType != TriggerType.Sphere)
             {
                 throw new ArgumentOutOfRangeException();
             }
             MyGamePruningStructure.GetAllTopMostEntitiesInSphere(ref this.m_boundingSphere, this.m_queryResult, MyEntityQueryType.Both);
         }
         int index = 0;
         while (index < this.m_queryResult.Count)
         {
             MyEntity entity = this.m_queryResult[index];
             if (!this.QueryEvaluator(entity))
             {
                 this.m_queryResult.RemoveAtFast <MyEntity>(index);
                 continue;
             }
             triggerType = this.m_triggerType;
             if (triggerType == TriggerType.AABB)
             {
                 if (!this.m_AABB.Intersects(this.m_queryResult[index].PositionComp.WorldAABB))
                 {
                     this.m_queryResult.RemoveAtFast <MyEntity>(index);
                     continue;
                 }
                 index++;
                 continue;
             }
             if (triggerType != TriggerType.Sphere)
             {
                 index++;
                 continue;
             }
             if (!this.m_boundingSphere.Intersects(this.m_queryResult[index].PositionComp.WorldAABB))
             {
                 this.m_queryResult.RemoveAtFast <MyEntity>(index);
                 continue;
             }
             index++;
         }
     }
 }
コード例 #6
0
        // For backwards compatbility we store areas that need to be cleared
        public void InitClearAreasManagement()
        {
            m_obstructorsPerSector = new Dictionary <long, List <MyOrientedBoundingBoxD> >();

            var interestArea = Planet.PositionComp.WorldAABB;

            List <MyEntity> entities = new List <MyEntity>();

            MyGamePruningStructure.GetTopMostEntitiesInBox(ref interestArea, entities);

            foreach (var entity in entities)
            {
                RasterSectorsForCollision(entity);
            }

            CollisionCheckEnabled = true;
        }
コード例 #7
0
        private static bool Conflicts(MyObjectBuilder_CubeGrid grid)
        {
            // Credits for this to KSH GitHub.
            var gridSize = MyDefinitionManager.Static.GetCubeSize(grid.GridSizeEnum);
            var localBb  = new BoundingBox(Vector3.MaxValue, Vector3.MinValue);

            foreach (var block in grid.CubeBlocks)
            {
                MyCubeBlockDefinition definition;
                if (!MyDefinitionManager.Static.TryGetCubeBlockDefinition(block.GetId(), out definition))
                {
                    continue;
                }
                MyBlockOrientation ori = block.BlockOrientation;
                var blockSize          = Vector3.TransformNormal(new Vector3(definition.Size) * gridSize, ori);
                blockSize = Vector3.Abs(blockSize);

                var minCorner = new Vector3(block.Min) * gridSize - new Vector3(gridSize / 2);
                var maxCorner = minCorner + blockSize;

                localBb.Include(minCorner);
                localBb.Include(maxCorner);
            }

            var worldAABB = ((BoundingBoxD)localBb).TransformFast(grid.PositionAndOrientation?.GetMatrix() ?? MatrixD.Identity);
            var list      = m_entityListPool.Get();

            list.Clear();
            MyGamePruningStructure.GetTopMostEntitiesInBox(ref worldAABB, list);
            foreach (var k in list)
            {
                var g     = k as IMyCubeGrid;
                var voxel = (k as IMyVoxelBase)?.PositionComp;
                if (g != null && g.WorldAABB.Intersects(worldAABB))
                {
                    return(true);
                }
                if (voxel != null && voxel.WorldVolume.Intersects(worldAABB))
                {
                    return(true);
                }
            }
            list.Clear();
            return(false);
        }
コード例 #8
0
ファイル: VoxelMapViewModel.cs プロジェクト: DrWathson/Torch
        public void UpdateAttachedGrids()
        {
            AttachedGrids.Clear();
            var box      = Entity.WorldAABB;
            var entities = new List <MyEntity>();

            MyGamePruningStructure.GetTopMostEntitiesInBox(ref box, entities, MyEntityQueryType.Static);
            foreach (var entity in entities.Where(e => e is IMyCubeGrid))
            {
                var gridModel = Tree.Grids.FirstOrDefault(g => g.Entity.EntityId == entity.EntityId);
                if (gridModel == null)
                {
                    gridModel = new GridViewModel((MyCubeGrid)entity, Tree);
                    Tree.Grids.Add(gridModel);
                }

                AttachedGrids.Add(gridModel);
            }
        }
コード例 #9
0
            public void DoWork(WorkData workData = null)
            {
                if (!_ref.TryGetTarget(out MyCubeGrid ent))
                {
                    return;
                }
                BalanceTick(ent);

                var aabb = ent.PositionComp.WorldAABB.Inflate(NextQueryDistance);

                _entityListPool.AllocateOrCreate(out var list);
                if (list == null)
                {
                    list = new List <MyEntity>();
                }
                try
                {
                    list.Clear();
                    MyGamePruningStructure.GetTopMostEntitiesInBox(ref aabb, list, MyEntityQueryType.Static);
                    var dt = (DateTime.Now - LastNearbyUpdate).TotalSeconds;
                    aabb = aabb.Inflate(Math.Min(dt * 30, NextQueryDistance));
                    MyGamePruningStructure.GetTopMostEntitiesInBox(ref aabb, list, MyEntityQueryType.Dynamic);
                    using (Lock.WriteUsing())
                    {
                        foreach (var k in NearbyEntities)
                        {
                            k.Free();
                        }
                        NearbyEntities.Clear();
                        foreach (var e in list)
                        {
                            NearbyEntities.Add(GCHandle.Alloc(e, GCHandleType.Weak));
                        }
                    }
                }
                finally
                {
                    _entityListPool.Deallocate(list);
                }
                LastNearbyUpdate = DateTime.Now;
            }
コード例 #10
0
        private Vector3D?FindSuitableJumpLocation(Vector3D desiredLocation)
        {
            BoundingBoxD shipBBox = GetAggregateBBox();

            // 1 Km distante to other objects to prevent spawning in bases
            shipBBox.Inflate(1000f);

            BoundingBoxD regionBBox = shipBBox.GetInflated(shipBBox.HalfExtents * 10);

            regionBBox.Translate(desiredLocation - regionBBox.Center);


            MyProceduralWorldGenerator.Static.OverlapAllPlanetSeedsInSphere(new BoundingSphereD(regionBBox.Center, regionBBox.HalfExtents.AbsMax()), m_objectsInRange);
            Vector3D currentSearchPosition = desiredLocation;

            foreach (var planet in m_objectsInRange)
            {
                if (planet.BoundingVolume.Contains(currentSearchPosition) != ContainmentType.Disjoint)
                {
                    Vector3D v = currentSearchPosition - planet.BoundingVolume.Center;
                    v.Normalize();
                    v *= planet.BoundingVolume.HalfExtents * 1.5;
                    currentSearchPosition = planet.BoundingVolume.Center + v;
                    break;
                }
            }
            m_objectsInRange.Clear();

            MyProceduralWorldGenerator.Static.OverlapAllAsteroidSeedsInSphere(new BoundingSphereD(regionBBox.Center, regionBBox.HalfExtents.AbsMax()), m_objectsInRange);
            foreach (var asteroid in m_objectsInRange)
            {
                m_obstaclesInRange.Add(asteroid.BoundingVolume);
            }
            m_objectsInRange.Clear();

            MyGamePruningStructure.GetTopMostEntitiesInBox(ref regionBBox, m_entitiesInRange);

            // Inflate the obstacles so we only need to check the center of the ship for collisions
            foreach (var entity in m_entitiesInRange)
            {
                if (!(entity is MyPlanet))
                {
                    m_obstaclesInRange.Add(entity.PositionComp.WorldAABB.GetInflated(shipBBox.HalfExtents));
                }
            }

            int maxStepCount = 10;
            int stepCount    = 0;

            // When we collide with an obsticle, we add it here
            BoundingBoxD?aggregateCollidedObstacles = null;
            bool         obstructed = false;
            bool         found      = false;

            while (stepCount < maxStepCount)
            {
                stepCount++;
                obstructed = false;
                foreach (var obstacle in m_obstaclesInRange)
                {
                    var contains = obstacle.Contains(currentSearchPosition);
                    if (contains == ContainmentType.Contains ||
                        contains == ContainmentType.Intersects)
                    {
                        if (!aggregateCollidedObstacles.HasValue)
                        {
                            aggregateCollidedObstacles = obstacle;
                        }
                        aggregateCollidedObstacles = aggregateCollidedObstacles.Value.Include(obstacle);
                        aggregateCollidedObstacles = aggregateCollidedObstacles.Value.Inflate(1.0);
                        currentSearchPosition      = ClosestPointOnBounds(aggregateCollidedObstacles.Value, currentSearchPosition);
                        obstructed = true;
                        break;
                    }
                }

                if (!obstructed)
                {
                    // No obstacle found, return current search position
                    found = true;
                    break;
                }
            }

            m_obstaclesInRange.Clear();
            m_entitiesInRange.Clear();
            m_objectsInRange.Clear();

            if (found)
            {
                return(currentSearchPosition);
            }
            else
            {
                return(null);
            }
        }
コード例 #11
0
        /// <summary>
        /// Override this function to set custom update behaviour.
        /// Call base at first because it queries objects if DoQuery is set.
        /// </summary>
        protected virtual void UpdateInternal()
        {
            if (DoQuery)
            {
                m_queryResult.Clear();

                switch (m_triggerType)
                {
                case TriggerType.AABB:
                    MyGamePruningStructure.GetTopMostEntitiesInBox(ref m_AABB, m_queryResult);
                    break;

                case TriggerType.Sphere:
                    MyGamePruningStructure.GetAllTopMostEntitiesInSphere(ref m_boundingSphere, m_queryResult);
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }


                for (int index = 0; index < m_queryResult.Count;)
                {
                    var result = m_queryResult[index];
                    if (!QueryEvaluator(result))
                    {
                        m_queryResult.RemoveAtFast(index);
                    }
                    else
                    {
                        switch (m_triggerType)
                        {
                        case TriggerType.AABB:
                            if (!m_AABB.Intersects(m_queryResult[index].PositionComp.WorldAABB))
                            {
                                m_queryResult.RemoveAtFast(index);
                            }
                            else
                            {
                                index++;
                            }
                            break;

                        case TriggerType.Sphere:
                            if (!m_boundingSphere.Intersects(m_queryResult[index].PositionComp.WorldAABB))
                            {
                                m_queryResult.RemoveAtFast(index);
                            }
                            else
                            {
                                index++;
                            }
                            break;

                        default:
                            index++;
                            break;
                        }
                    }
                }
            }
        }
コード例 #12
0
        internal void MonitorRefreshTasks(int x, ref List <MyEntity> monitorList, bool reInforce, ref bool newSub)
        {
            var s = _workData.ShieldList[x];

            if (reInforce)
            {
                var newMode = !s.ReInforcedShield;
                if (!newMode)
                {
                    return;
                }

                HashSet <MyCubeGrid> subs;
                lock (s.SubLock)
                {
                    subs = SetMyCubeGridPool.Get();
                    subs.UnionWith(s.ShieldComp.SubGrids);
                }
                foreach (var sub in subs)
                {
                    if (!_globalEntTmp.ContainsKey(sub))
                    {
                        newSub = true;
                    }
                    _entRefreshQueue.Enqueue(sub);
                    if (!s.WasPaused)
                    {
                        _globalEntTmp[sub] = _workData.Tick;
                    }
                }
                subs.Clear();
                SetMyCubeGridPool.Return(subs);

                s.ReInforcedShield    = true;
                s.TicksWithNoActivity = 0;
                s.LastWokenTick       = _workData.Tick;
                s.Asleep = false;
            }
            else
            {
                var newMode = false;
                if (s.ReInforcedShield)
                {
                    HashSet <MyCubeGrid> subs;
                    lock (s.SubLock)
                    {
                        subs = SetMyCubeGridPool.Get();
                        subs.UnionWith(s.ShieldComp.SubGrids);
                    }
                    foreach (var sub in subs)
                    {
                        _entRefreshQueue.Enqueue(sub);
                        if (!s.WasPaused)
                        {
                            _globalEntTmp[sub] = _workData.Tick;
                        }
                    }
                    subs.Clear();
                    SetMyCubeGridPool.Return(subs);

                    //if (Enforced.Debug >= 2) Log.Line($"found Reinforce");
                    s.ReInforcedShield    = false;
                    s.TicksWithNoActivity = 0;
                    s.LastWokenTick       = _workData.Tick;
                    s.Asleep = false;
                    newMode  = true;
                }

                if (!newMode)
                {
                    var foundNewEnt   = false;
                    var disableVoxels = Enforced.DisableVoxelSupport == 1 || s.ShieldComp.Modulator == null || s.ShieldComp.Modulator.ModSet.Settings.ModulateVoxels;
                    MyGamePruningStructure.GetTopmostEntitiesInBox(ref s.WebBox, monitorList);
                    if (!s.WasPaused)
                    {
                        foreach (var ent in monitorList)
                        {
                            var voxel = ent as MyVoxelBase;
                            if (ent == null || ent.MarkedForClose || (voxel == null && (ent.Physics == null || ent.Physics.IsPhantom || ent.DefinitionId == null)) || (!s.GridIsMobile && voxel != null) || (disableVoxels && voxel != null) || (voxel != null && voxel != voxel.RootVoxel))
                            {
                                continue;
                            }

                            if (ent is IMyFloatingObject || ent is IMyEngineerToolBase || !s.WebSphere.Intersects(ent.PositionComp.WorldVolume))
                            {
                                continue;
                            }

                            if (CustomCollision.NewObbPointsInShield(ent, s.DetectMatrixOutsideInv) > 0)
                            {
                                if (!_globalEntTmp.ContainsKey(ent))
                                {
                                    foundNewEnt = true;
                                    s.Asleep    = false;
                                }

                                _globalEntTmp[ent] = _workData.Tick;
                            }
                            s.NewEntByShield = foundNewEnt;
                        }
                    }
                    else
                    {
                        s.NewEntByShield = false;
                    }

                    if (!s.NewEntByShield)
                    {
                        var foundPlayer = false;
                        foreach (var player in Players.Values)
                        {
                            var character = player.Character;
                            if (character == null)
                            {
                                continue;
                            }

                            if (Vector3D.DistanceSquared(character.PositionComp.WorldMatrixRef.Translation, s.DetectionCenter) < SyncDistSqr)
                            {
                                foundPlayer = true;
                                break;
                            }
                        }
                        s.PlayerByShield = foundPlayer;
                    }
                    if (!s.PlayerByShield)
                    {
                        s.MoverByShield = false;
                        var newMover = false;

                        var moverList = ListMyEntityPool.Get();
                        MyGamePruningStructure.GetTopMostEntitiesInBox(ref s.ShieldBox3K, moverList, MyEntityQueryType.Dynamic);
                        for (int i = 0; i < moverList.Count; i++)
                        {
                            var ent = moverList[i];

                            var meteor = ent as IMyMeteor;
                            if (meteor != null)
                            {
                                if (CustomCollision.FutureIntersect(s, ent, s.DetectMatrixOutside, s.DetectMatrixOutsideInv))
                                {
                                    if (Enforced.Debug >= 2)
                                    {
                                        Log.Line($"[Future Intersecting Meteor] distance from shieldCenter: {Vector3D.Distance(s.DetectionCenter, ent.WorldMatrix.Translation)} - waking:");
                                    }
                                    newMover = true;
                                    break;
                                }
                                continue;
                            }

                            if (!(ent.Physics == null || ent.Physics.IsPhantom || ent is MyCubeGrid || ent is IMyCharacter))
                            {
                                continue;
                            }
                            var entPos = ent.PositionComp.WorldAABB.Center;

                            var keyFound = s.EntsByMe.ContainsKey(ent);
                            if (keyFound)
                            {
                                if (!s.EntsByMe[ent].Pos.Equals(entPos, 1e-3))
                                {
                                    MoverInfo moverInfo;
                                    s.EntsByMe.TryRemove(ent, out moverInfo);
                                    s.EntsByMe.TryAdd(ent, new MoverInfo(entPos, _workData.Tick));
                                    if (moverInfo.CreationTick == _workData.Tick - 1)
                                    {
                                        if (Enforced.Debug >= 3 && s.WasPaused)
                                        {
                                            Log.Line($"[Moved] Ent:{ent.DebugName} - howMuch:{Vector3D.Distance(entPos, s.EntsByMe[ent].Pos)} - ShieldId [{s.Shield.EntityId}]");
                                        }
                                        newMover = true;
                                    }
                                    break;
                                }
                            }
                            else
                            {
                                if (Enforced.Debug >= 3)
                                {
                                    Log.Line($"[NewMover] Ent:{ent.DebugName} - ShieldId [{s.Shield.EntityId}]");
                                }
                                s.EntsByMe.TryAdd(ent, new MoverInfo(entPos, _workData.Tick));
                            }
                        }
                        moverList.Clear();
                        ListMyEntityPool.Return(moverList);

                        s.MoverByShield = newMover;
                    }

                    if (_workData.Tick < s.LastWokenTick + 400)
                    {
                        s.Asleep = false;
                        return;
                    }
                }

                if (s.EntCleanUpTime)
                {
                    s.EntCleanUpTime = false;
                    if (!s.EntsByMe.IsEmpty)
                    {
                        var entsByMeTmp = new List <KeyValuePair <MyEntity, MoverInfo> >();
                        entsByMeTmp.AddRange(s.EntsByMe.Where(info => !info.Key.InScene || _workData.Tick - info.Value.CreationTick > EntMaxTickAge));
                        for (int i = 0; i < entsByMeTmp.Count; i++)
                        {
                            MoverInfo mInfo;
                            s.EntsByMe.TryRemove(entsByMeTmp[i].Key, out mInfo);
                        }
                    }
                }
            }
        }
コード例 #13
0
        public void WebEntities()
        {
            PruneList.Clear();
            MyGamePruningStructure.GetTopMostEntitiesInBox(ref WebBox, PruneList);
            if (Missiles.Count > 0)
            {
                var missileBox = WebBox;
                foreach (var missile in Missiles)
                {
                    if (missile.InScene && !missile.MarkedForClose && missileBox.Intersects(missile.PositionComp.WorldAABB))
                    {
                        PruneList.Add(missile);
                    }
                }
            }
            var shieldsStartIndex = PruneList.Count;

            foreach (var eShield in EnemyShields)
            {
                PruneList.Add(eShield);
            }

            var disableVoxels = Session.Enforced.DisableVoxelSupport == 1 || ShieldComp.Modulator == null || ShieldComp.Modulator.ModSet.Settings.ModulateVoxels;
            var voxelFound    = false;
            var shieldFound   = false;
            var entChanged    = false;
            var iMoving       = ShieldComp.GridIsMoving;
            var tick          = Session.Instance.Tick;

            _enablePhysics = false;
            for (int i = 0; i < PruneList.Count; i++)
            {
                var ent        = PruneList[i];
                var entPhysics = ent.Physics;

                if (i < shieldsStartIndex)
                {
                    var voxel = ent as MyVoxelBase;
                    if (ent == null || (voxel == null && (entPhysics == null || entPhysics.IsPhantom || ent.DefinitionId == null)) || (voxel != null && (!iMoving || !GridIsMobile || disableVoxels || voxel != voxel.RootVoxel)))
                    {
                        continue;
                    }

                    bool quickReject;
                    if (_isServer)
                    {
                        quickReject = ent is IMyEngineerToolBase || IgnoreCache.Contains(ent) || EnemyShields.Contains(ent) || FriendlyMissileCache.Contains(ent) || AuthenticatedCache.Contains(ent);
                    }
                    else
                    {
                        quickReject = (!(ent is MyCubeGrid) && voxel == null && !(ent is IMyCharacter)) || IgnoreCache.Contains(ent) || EnemyShields.Contains(ent) || AuthenticatedCache.Contains(ent);
                    }

                    var floater = ent as IMyFloatingObject;
                    if (quickReject || floater != null && (!iMoving && Vector3.IsZero(entPhysics.LinearVelocity, 1e-2f)) || !WebSphere.Intersects(ent.PositionComp.WorldVolume))
                    {
                        continue;
                    }
                    if (voxel != null)
                    {
                        if (VoxelsToIntersect.ContainsKey(voxel))
                        {
                            VoxelsToIntersect[voxel]++;
                        }
                        else
                        {
                            VoxelsToIntersect[voxel] = 1;
                        }
                        voxelFound     = true;
                        entChanged     = true;
                        _enablePhysics = true;
                        continue;
                    }
                }
                Ent relation;

                ProtectCache     protectedEnt;
                EntIntersectInfo entInfo = null;
                ProtectedEntCache.TryGetValue(ent, out protectedEnt);

                var refreshInfo = false;
                if (protectedEnt == null)
                {
                    WebEnts.TryGetValue(ent, out entInfo);
                    if (entInfo != null)
                    {
                        var last        = entInfo.LastTick;
                        var refresh     = entInfo.RefreshTick;
                        var refreshTick = tick - last > 180 || (tick - last == 180 && tick - refresh >= 3600) || (tick - last == 1 && tick - refresh >= 60);
                        refreshInfo = refreshTick;
                        if (refreshInfo || entInfo.RefreshNow)
                        {
                            entInfo.RefreshTick = tick;
                            entInfo.Relation    = EntType(ent);
                        }
                        relation         = entInfo.Relation;
                        entInfo.LastTick = tick;
                    }
                    else
                    {
                        relation = EntType(ent);
                    }
                }
                else
                {
                    var last        = protectedEnt.LastTick;
                    var refresh     = protectedEnt.RefreshTick;
                    var refreshTick = tick - last > 180 || (tick - last == 180 && tick - refresh >= 3600) || (tick - last == 1 && tick - refresh >= 60);
                    refreshInfo = refreshTick;
                    if (refreshInfo)
                    {
                        protectedEnt.RefreshTick      = tick;
                        protectedEnt.PreviousRelation = protectedEnt.Relation;
                        protectedEnt.Relation         = EntType(ent);
                    }
                    relation = protectedEnt.Relation;
                    protectedEnt.LastTick = tick;
                }
                switch (relation)
                {
                case Ent.Authenticated:
                    continue;

                case Ent.Ignore:
                case Ent.Friendly:
                case Ent.Protected:
                    if (relation == Ent.Protected)
                    {
                        if (protectedEnt == null)
                        {
                            ProtectedEntCache[ent] = new ProtectCache(tick, tick, tick, relation, relation);
                        }
                        MyProtectors protectors;
                        Session.Instance.GlobalProtect.TryGetValue(ent, out protectors);
                        if (protectors == null)
                        {
                            protectors = Session.Instance.GlobalProtect[ent] = Session.ProtSets.Get();
                            protectors.Init(LogicSlot, tick);
                        }
                        if (protectors.Shields.Contains(this))
                        {
                            continue;
                        }

                        protectors.Shields.Add(this);
                        protectors.Shields.ApplyAdditions();
                        continue;
                    }
                    IgnoreCache.Add(ent);
                    continue;
                }

                if (relation == Ent.Shielded)
                {
                    shieldFound = true;
                }
                try
                {
                    if (entInfo != null)
                    {
                        var interestingEnts = relation == Ent.Floater || relation == Ent.EnemyGrid || relation == Ent.NobodyGrid || relation == Ent.Shielded;
                        if (entPhysics != null && entPhysics.IsMoving)
                        {
                            entChanged = true;
                        }
                        else if (entInfo.Touched || (refreshInfo && interestingEnts && !ent.PositionComp.LocalAABB.Equals(entInfo.Box)))
                        {
                            entInfo.RefreshTick = tick;
                            entInfo.Box         = ent.PositionComp.LocalAABB;
                            entChanged          = true;
                        }

                        _enablePhysics = true;
                        if (refreshInfo)
                        {
                            if ((relation == Ent.EnemyGrid || relation == Ent.NobodyGrid) && entInfo.CacheBlockList.Count != (ent as MyCubeGrid).BlocksCount)
                            {
                                entInfo.RefreshNow = true;
                            }
                        }
                    }
                    else
                    {
                        if (relation == Ent.Other)
                        {
                            var entPast      = -Vector3D.Normalize(entPhysics.LinearVelocity) * 6;
                            var entTestLoc   = ent.PositionComp.WorldVolume.Center + entPast;
                            var centerStep   = -Vector3D.Normalize(entTestLoc - DetectionCenter) * 2f;
                            var counterDrift = centerStep + entTestLoc;
                            if (CustomCollision.PointInShield(counterDrift, DetectMatrixOutsideInv))
                            {
                                FriendlyMissileCache.Add(ent);
                                continue;
                            }
                        }
                        entChanged     = true;
                        _enablePhysics = true;
                        ProtectedEntCache.Remove(ent);
                        WebEnts.TryAdd(ent, new EntIntersectInfo(false, ent.PositionComp.LocalAABB, tick, tick, tick, relation));
                    }
                }
                catch (Exception ex) { Log.Line($"Exception in WebEntities entInfo: {ex}"); }
            }
            if (!_enablePhysics)
            {
                return;
            }

            ShieldMatrix = ShieldEnt.PositionComp.WorldMatrix;
            if ((_needPhysics && shieldFound) || !ShieldMatrix.EqualsFast(ref OldShieldMatrix))
            {
                OldShieldMatrix = ShieldMatrix;
                if (shieldFound)
                {
                    _needPhysics = false;
                    Icosphere.ReturnPhysicsVerts(DetectMatrixOutside, ShieldComp.PhysicsOutside);
                }
                else
                {
                    _needPhysics = true;
                }
                if (voxelFound)
                {
                    Icosphere.ReturnPhysicsVerts(DetectMatrixOutside, ShieldComp.PhysicsOutsideLow);
                }
            }

            if (iMoving || entChanged)
            {
                Asleep        = false;
                LastWokenTick = tick;
                Session.Instance.WebWrapper.Enqueue(this);
                Session.Instance.WebWrapperOn = true;
            }
        }
コード例 #14
0
        private void UpdateOxygen()
        {
            MyOxygenRoom    room;
            List <MyEntity> result          = new List <MyEntity>();
            BoundingBoxD    worldAABB       = base.Character.PositionComp.WorldAABB;
            bool            enableOxygen    = MySession.Static.Settings.EnableOxygen;
            bool            noOxygenDamage  = MySession.Static.Settings.EnableOxygen;
            bool            isInEnvironment = true;
            bool            flag4           = false;

            if (!Sync.IsServer)
            {
                goto TR_000A;
            }
            else
            {
                base.Character.EnvironmentOxygenLevelSync.Value     = MyOxygenProviderSystem.GetOxygenInPoint(base.Character.PositionComp.GetPosition());
                base.Character.OxygenLevelAtCharacterLocation.Value = base.Character.EnvironmentOxygenLevel;
                room = null;
                if (!MySession.Static.Settings.EnableOxygen)
                {
                    goto TR_000C;
                }
                else
                {
                    GasData data;
                    if (this.TryGetGasData(OxygenId, out data))
                    {
                        float num = (MySession.Static.GameplayFrameCounter - data.LastOutputTime) * 0.01666667f;
                        flag4 = (this.CharacterGasSink.CurrentInputByType(OxygenId) * num) > this.Definition.OxygenConsumption;
                        if (flag4)
                        {
                            noOxygenDamage = false;
                            enableOxygen   = false;
                        }
                    }
                    MyCockpit parent = base.Character.Parent as MyCockpit;
                    bool      flag5  = false;
                    if ((parent != null) && parent.BlockDefinition.IsPressurized)
                    {
                        if ((!this.HelmetEnabled && (MySession.Static.SurvivalMode && !flag4)) && (parent.OxygenAmount >= (this.Definition.OxygenConsumption * this.Definition.OxygenConsumptionMultiplier)))
                        {
                            parent.OxygenAmount -= this.Definition.OxygenConsumption * this.Definition.OxygenConsumptionMultiplier;
                            noOxygenDamage       = false;
                            enableOxygen         = false;
                        }
                        base.Character.EnvironmentOxygenLevelSync.Value = parent.OxygenFillLevel;
                        isInEnvironment = false;
                        flag5           = true;
                    }
                    if (!flag5 || (MyFakes.ENABLE_NEW_SOUNDS && MySession.Static.Settings.RealisticSound))
                    {
                        base.Character.OxygenSourceGridEntityId.Value = 0L;
                        Vector3D center = base.Character.PositionComp.WorldAABB.Center;
                        MyGamePruningStructure.GetTopMostEntitiesInBox(ref worldAABB, result, MyEntityQueryType.Both);
                        using (List <MyEntity> .Enumerator enumerator = result.GetEnumerator())
                        {
                            while (true)
                            {
                                while (true)
                                {
                                    if (enumerator.MoveNext())
                                    {
                                        MyCubeGrid current = enumerator.Current as MyCubeGrid;
                                        if (current == null)
                                        {
                                            continue;
                                        }
                                        if (current.GridSystems.GasSystem == null)
                                        {
                                            continue;
                                        }
                                        MyOxygenBlock safeOxygenBlock = current.GridSystems.GasSystem.GetSafeOxygenBlock(center);
                                        if (safeOxygenBlock == null)
                                        {
                                            continue;
                                        }
                                        if (safeOxygenBlock.Room == null)
                                        {
                                            continue;
                                        }
                                        room = safeOxygenBlock.Room;
                                        if ((room.OxygenLevel(current.GridSize) > this.Definition.PressureLevelForLowDamage) && !this.HelmetEnabled)
                                        {
                                            enableOxygen = false;
                                        }
                                        if (!room.IsAirtight)
                                        {
                                            float environmentOxygen = room.EnvironmentOxygen;
                                            base.Character.OxygenLevelAtCharacterLocation.Value = environmentOxygen;
                                            if (flag5)
                                            {
                                                break;
                                            }
                                            base.Character.EnvironmentOxygenLevelSync.Value = environmentOxygen;
                                            if (this.HelmetEnabled)
                                            {
                                                break;
                                            }
                                            if (base.Character.EnvironmentOxygenLevelSync.Value <= (this.Definition.OxygenConsumption * this.Definition.OxygenConsumptionMultiplier))
                                            {
                                                break;
                                            }
                                            noOxygenDamage = false;
                                        }
                                        else
                                        {
                                            float num2 = room.OxygenLevel(current.GridSize);
                                            if (!flag5)
                                            {
                                                base.Character.EnvironmentOxygenLevelSync.Value = num2;
                                            }
                                            base.Character.OxygenLevelAtCharacterLocation.Value = num2;
                                            base.Character.OxygenSourceGridEntityId.Value       = current.EntityId;
                                            if (room.OxygenAmount <= (this.Definition.OxygenConsumption * this.Definition.OxygenConsumptionMultiplier))
                                            {
                                                break;
                                            }
                                            if (!this.HelmetEnabled)
                                            {
                                                noOxygenDamage = false;
                                                safeOxygenBlock.PreviousOxygenAmount = safeOxygenBlock.OxygenAmount() - (this.Definition.OxygenConsumption * this.Definition.OxygenConsumptionMultiplier);
                                                safeOxygenBlock.OxygenChangeTime     = MySandboxGame.TotalGamePlayTimeInMilliseconds;
                                                if (!flag4)
                                                {
                                                    room.OxygenAmount -= this.Definition.OxygenConsumption * this.Definition.OxygenConsumptionMultiplier;
                                                }
                                            }
                                        }
                                        goto TR_000D;
                                    }
                                    else
                                    {
                                        goto TR_000D;
                                    }
                                    break;
                                }
                                isInEnvironment = false;
                            }
                        }
                    }
                }
            }
            goto TR_000D;
TR_000A:
            this.CharacterGasSink.Update();
            if (Sync.IsServer && !MySession.Static.CreativeMode)
            {
                this.RefillSuitGassesFromBottles();
                if (MySession.Static.Settings.EnableOxygen)
                {
                    this.UpdateSuitOxygen(enableOxygen, noOxygenDamage, isInEnvironment);
                }
                foreach (GasData data2 in this.m_storedGases)
                {
                    base.Character.UpdateStoredGas(data2.Id, data2.FillLevel);
                }
            }
            return;

TR_000C:
            this.UpdateGassesFillLevelsAndAmounts(room);
            goto TR_000A;
TR_000D:
            this.m_oldSuitOxygenLevel = this.SuitOxygenLevel;
            goto TR_000C;
        }
コード例 #15
0
        internal void MonitorRefreshTasks(int x, ref List <MyEntity> monitorList, bool reInforce, ref bool newSub)
        {
            var s = _workData.ShieldList[x];

            if (reInforce)
            {
                HashSet <MyCubeGrid> subs;
                lock (s.GetCubesLock) subs = new HashSet <MyCubeGrid>(s.ShieldComp.GetSubGrids);
                var newMode = !s.ReInforcedShield;
                if (!newMode)
                {
                    return;
                }
                foreach (var sub in subs)
                {
                    //if (Enforced.Debug >= 2) Log.Line("Server queuing entFresh for reinforced shield");

                    if (!_globalEntTmp.ContainsKey(sub))
                    {
                        newSub = true;
                    }
                    _entRefreshQueue.Enqueue(sub);
                    if (!s.WasPaused)
                    {
                        _globalEntTmp[sub] = _workData.Tick;
                    }
                }

                s.ReInforcedShield    = true;
                s.TicksWithNoActivity = 0;
                s.LastWokenTick       = _workData.Tick;
                s.Asleep = false;
            }
            else
            {
                var newMode = false;
                if (s.ReInforcedShield)
                {
                    HashSet <MyCubeGrid> subs;
                    lock (s.GetCubesLock) subs = new HashSet <MyCubeGrid>(s.ShieldComp.GetSubGrids);
                    foreach (var sub in subs)
                    {
                        _entRefreshQueue.Enqueue(sub);
                        if (!s.WasPaused)
                        {
                            _globalEntTmp[sub] = _workData.Tick;
                        }
                    }
                    //if (Enforced.Debug >= 2) Log.Line($"found Reinforce");
                    s.ReInforcedShield    = false;
                    s.TicksWithNoActivity = 0;
                    s.LastWokenTick       = _workData.Tick;
                    s.Asleep = false;
                    newMode  = true;
                }

                if (!newMode)
                {
                    // var testMat = s.DetectMatrixOutside;
                    // var shape1 = new Sphere(Vector3D.Zero, 1.0).Transformed(testMat);
                    var foundNewEnt   = false;
                    var disableVoxels = Enforced.DisableVoxelSupport == 1 || s.ShieldComp.Modulator == null || s.ShieldComp.Modulator.ModSet.Settings.ModulateVoxels;
                    MyGamePruningStructure.GetTopmostEntitiesInBox(ref s.WebBox, monitorList);
                    foreach (var ent in monitorList)
                    {
                        var voxel = ent as MyVoxelBase;
                        if (ent == null || ent.MarkedForClose || (voxel == null && (ent.Physics == null || ent.DefinitionId == null)) || (!s.GridIsMobile && voxel != null) || (disableVoxels && voxel != null) || (voxel != null && voxel != voxel.RootVoxel))
                        {
                            continue;
                        }

                        if (ent is IMyFloatingObject || ent is IMyEngineerToolBase || !s.WebSphere.Intersects(ent.PositionComp.WorldVolume))
                        {
                            continue;
                        }

                        // var halfExtents = ent.PositionComp.LocalAABB.HalfExtents;
                        // if (halfExtents.X < 1) halfExtents.X = 10;
                        // if (halfExtents.Y < 1) halfExtents.Y = 10;
                        // if (halfExtents.Z < 1) halfExtents.Z = 10;
                        // var shape2 = new Box(-halfExtents, halfExtents).Transformed(ent.WorldMatrix);
                        // var test = Gjk.Intersects(ref shape1, ref shape2);
                        // Log.Line($"{ent.DebugName} - {test}");
                        if (CustomCollision.NewObbPointsInShield(ent, s.DetectMatrixOutsideInv) > 0)
                        {
                            if (!s.WasPaused && !_globalEntTmp.ContainsKey(ent))
                            {
                                foundNewEnt = true;
                                s.Asleep    = false;
                                //if (Enforced.Debug >= 2) Log.Line($"New entity");
                            }

                            if (!s.WasPaused)
                            {
                                _globalEntTmp[ent] = _workData.Tick;
                            }
                        }
                        s.NewEntByShield = foundNewEnt;
                    }
                    if (!s.NewEntByShield)
                    {
                        var foundPlayer = false;
                        foreach (var player in Players.Values)
                        {
                            var character = player.Character;
                            if (character == null)
                            {
                                continue;
                            }

                            if (Vector3D.DistanceSquared(character.PositionComp.WorldMatrix.Translation, s.DetectionCenter) < SyncDistSqr)
                            {
                                foundPlayer = true;
                                break;
                            }
                        }
                        s.PlayerByShield = foundPlayer;
                    }
                    if (!s.PlayerByShield)
                    {
                        s.MoverByShield = false;
                        var newMover  = false;
                        var moverList = new List <MyEntity>();

                        MyGamePruningStructure.GetTopMostEntitiesInBox(ref s.ShieldBox3K, moverList, MyEntityQueryType.Dynamic);
                        for (int i = 0; i < moverList.Count; i++)
                        {
                            var ent = moverList[i];

                            if (!(ent.Physics == null || ent is MyCubeGrid || ent is IMyCharacter || ent is IMyMeteor))
                            {
                                continue;
                            }
                            var entPos = ent.PositionComp.WorldMatrix.Translation;

                            var keyFound = s.EntsByMe.ContainsKey(ent);
                            if (keyFound)
                            {
                                if (!s.EntsByMe[ent].Pos.Equals(entPos, 1e-3))
                                {
                                    //if (Enforced.Debug >= 2) Log.Line($"[Moved] Ent:{ent.DebugName}");
                                    MoverInfo moverInfo;
                                    s.EntsByMe.TryRemove(ent, out moverInfo);
                                    s.EntsByMe.TryAdd(ent, new MoverInfo(entPos, _workData.Tick));
                                    newMover = true;
                                    break;
                                }
                            }
                            else
                            {
                                s.EntsByMe.TryAdd(ent, new MoverInfo(entPos, _workData.Tick));
                            }
                        }
                        s.MoverByShield = newMover;
                    }

                    if (_workData.Tick < s.LastWokenTick + 400)
                    {
                        s.Asleep = false;
                        return;
                    }
                }

                if (s.EntCleanUpTime)
                {
                    s.EntCleanUpTime = false;
                    if (!s.EntsByMe.IsEmpty)
                    {
                        var entsByMeTmp = new List <KeyValuePair <MyEntity, MoverInfo> >();
                        entsByMeTmp.AddRange(s.EntsByMe.Where(info => !info.Key.InScene || _workData.Tick - info.Value.CreationTick > EntMaxTickAge));
                        for (int i = 0; i < entsByMeTmp.Count; i++)
                        {
                            MoverInfo mInfo;
                            s.EntsByMe.TryRemove(entsByMeTmp[i].Key, out mInfo);
                        }
                    }
                }
            }
        }
コード例 #16
0
        private void UpdateOxygen()
        {
            // Try to find grids that might contain oxygen
            var entities = new List <MyEntity>();
            var aabb     = Character.PositionComp.WorldAABB;

            bool lowOxygenDamage   = MySession.Static.Settings.EnableOxygen;
            bool noOxygenDamage    = MySession.Static.Settings.EnableOxygen;
            bool isInEnvironment   = true;
            bool oxygenReplenished = false;

            EnvironmentOxygenLevel         = MyOxygenProviderSystem.GetOxygenInPoint(Character.PositionComp.GetPosition());
            OxygenLevelAtCharacterLocation = EnvironmentOxygenLevel;

            if (Sync.IsServer)
            {
                // Check for possibility that we are replenishing oxygen
                if (MySession.Static.Settings.EnableOxygen)
                {
                    GasData oxygenData;
                    if (TryGetGasData(OxygenId, out oxygenData))
                    {
                        float timeSinceLastUpdateSeconds = (MySession.Static.GameplayFrameCounter - oxygenData.LastOutputTime) * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS;

                        oxygenReplenished = CharacterGasSink.CurrentInputByType(OxygenId) * timeSinceLastUpdateSeconds > Definition.OxygenConsumption;

                        if (oxygenReplenished)
                        {
                            noOxygenDamage  = false;
                            lowOxygenDamage = false;
                        }
                    }
                }

                // Update Gases fill levels and capacity amounts
                foreach (GasData gasInfo in m_storedGases)
                {
                    var timeSinceLastOutputSeconds = (MySession.Static.GameplayFrameCounter - gasInfo.LastOutputTime) * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS;
                    var timeSinceLastInputSeconds  = (MySession.Static.GameplayFrameCounter - gasInfo.LastInputTime) * VRage.Game.MyEngineConstants.UPDATE_STEP_SIZE_IN_SECONDS;

                    gasInfo.LastOutputTime = MySession.Static.GameplayFrameCounter;
                    gasInfo.LastInputTime  = MySession.Static.GameplayFrameCounter;

                    float gasOutputAmount = CharacterGasSource.CurrentOutputByType(gasInfo.Id) * timeSinceLastOutputSeconds;
                    float gasInputAmount  = CharacterGasSink.CurrentInputByType(gasInfo.Id) * timeSinceLastInputSeconds;

                    // Values that are not in distribution system yet and happend to inc/dec between updates
                    float outTransfer = -MathHelper.Clamp(gasInfo.NextGasTransfer, float.NegativeInfinity, 0f);
                    float inTransfer  = MathHelper.Clamp(gasInfo.NextGasTransfer, 0f, float.PositiveInfinity);
                    gasInfo.NextGasTransfer = 0f;

                    TransferSuitGas(ref gasInfo.Id, gasInputAmount + inTransfer, gasOutputAmount + outTransfer);
                }
            }

            if (MySession.Static.Settings.EnableOxygen)
            {
                var  cockpit           = Character.Parent as MyCockpit;
                bool OxygenFromCockpit = false;
                if (cockpit != null && cockpit.BlockDefinition.IsPressurized)
                {
                    if (Sync.IsServer && MySession.Static.SurvivalMode && !oxygenReplenished)
                    {
                        // Character is in pressurized room
                        if (!HelmetEnabled)
                        {
                            if (cockpit.OxygenFillLevel > 0f)
                            {
                                if (cockpit.OxygenAmount >= Definition.OxygenConsumption * Definition.OxygenConsumptionMultiplier)
                                {
                                    cockpit.OxygenAmount -= Definition.OxygenConsumption * Definition.OxygenConsumptionMultiplier;

                                    noOxygenDamage  = false;
                                    lowOxygenDamage = false;
                                }
                            }
                        }
                    }
                    EnvironmentOxygenLevel = cockpit.OxygenFillLevel;
                    isInEnvironment        = false;
                    OxygenFromCockpit      = true;
                }

                if (OxygenFromCockpit == false || (MyFakes.ENABLE_NEW_SOUNDS && MySession.Static.Settings.RealisticSound))
                {
                    OxygenSourceGrid = null;
                    Vector3D pos = Character.GetHeadMatrix(true, true, false, true).Translation;

                    MyGamePruningStructure.GetTopMostEntitiesInBox(ref aabb, entities);
                    foreach (var entity in entities)
                    {
                        var grid = entity as MyCubeGrid;
                        // Oxygen can be present on small grids as well because of mods
                        if (grid != null && grid.GridSystems.GasSystem != null)
                        {
                            var oxygenBlock = grid.GridSystems.GasSystem.GetSafeOxygenBlock(pos);
                            if (oxygenBlock.Room != null)
                            {
                                if (oxygenBlock.Room.OxygenLevel(grid.GridSize) > Definition.PressureLevelForLowDamage)
                                {
                                    if (!HelmetEnabled)
                                    {
                                        lowOxygenDamage = false;
                                    }
                                }

                                if (oxygenBlock.Room.IsPressurized)
                                {
                                    float oxygen = oxygenBlock.Room.OxygenLevel(grid.GridSize);
                                    if (!OxygenFromCockpit)
                                    {
                                        EnvironmentOxygenLevel = oxygen;
                                    }
                                    OxygenLevelAtCharacterLocation = oxygen;
                                    OxygenSourceGrid = grid;
                                    if (oxygenBlock.Room.OxygenAmount > Definition.OxygenConsumption * Definition.OxygenConsumptionMultiplier)
                                    {
                                        if (!HelmetEnabled)
                                        {
                                            noOxygenDamage = false;
                                            oxygenBlock.PreviousOxygenAmount = oxygenBlock.OxygenAmount() - Definition.OxygenConsumption * Definition.OxygenConsumptionMultiplier;
                                            oxygenBlock.OxygenChangeTime     = MySandboxGame.TotalGamePlayTimeInMilliseconds;

                                            if (!oxygenReplenished)
                                            {
                                                oxygenBlock.Room.OxygenAmount -= Definition.OxygenConsumption * Definition.OxygenConsumptionMultiplier;
                                            }
                                        }
                                        break;
                                    }
                                }
                                else
                                {
                                    float oxygen = oxygenBlock.Room.EnvironmentOxygen;
                                    OxygenLevelAtCharacterLocation = oxygen;

                                    if (!OxygenFromCockpit)
                                    {
                                        EnvironmentOxygenLevel = oxygen;

                                        if (!HelmetEnabled && EnvironmentOxygenLevel > Definition.OxygenConsumption * Definition.OxygenConsumptionMultiplier)
                                        {
                                            noOxygenDamage = false;
                                            break;
                                        }
                                    }
                                }

                                isInEnvironment = false;
                            }
                        }
                    }
                }


                if (MySession.Static.LocalCharacter == Character)
                {
                    if (m_oldSuitOxygenLevel >= 0.25f && SuitOxygenLevel < 0.25f)
                    {
                        MyHud.Notifications.Add(m_lowOxygenNotification);
                    }
                    else if (m_oldSuitOxygenLevel >= 0.05f && SuitOxygenLevel < 0.05f)
                    {
                        MyHud.Notifications.Add(m_criticalOxygenNotification);
                    }
                }
                m_oldSuitOxygenLevel = SuitOxygenLevel;
            }
            CharacterGasSink.Update();

            // Cannot early exit before calculations because of UI
            if (!Sync.IsServer || MySession.Static.CreativeMode || !MySession.Static.Settings.EnableOxygen)
            {
                return;
            }

            foreach (var gasInfo in m_storedGases)
            {
                if (gasInfo.FillLevel < GAS_REFILL_RATION) // Get rid of the specific oxygen version of this
                {
                    if (gasInfo.NextGasRefill == -1)
                    {
                        gasInfo.NextGasRefill = MySandboxGame.TotalGamePlayTimeInMilliseconds + m_gasRefillInterval * 1000;
                    }
                    if (MySandboxGame.TotalGamePlayTimeInMilliseconds < gasInfo.NextGasRefill)
                    {
                        continue;
                    }

                    gasInfo.NextGasRefill = -1;

                    var  items       = Character.GetInventory().GetItems();
                    bool bottlesUsed = false;
                    foreach (var item in items)
                    {
                        var gasContainer = item.Content as MyObjectBuilder_GasContainerObject;
                        if (gasContainer != null)
                        {
                            if (gasContainer.GasLevel == 0f)
                            {
                                continue;
                            }

                            var physicalItem = MyDefinitionManager.Static.GetPhysicalItemDefinition(gasContainer) as MyOxygenContainerDefinition;
                            if (physicalItem.StoredGasId != gasInfo.Id)
                            {
                                continue;
                            }
                            float gasAmount = gasContainer.GasLevel * physicalItem.Capacity;

                            float transferredAmount = Math.Min(gasAmount, (1f - gasInfo.FillLevel) * gasInfo.MaxCapacity);
                            gasContainer.GasLevel = Math.Max((gasAmount - transferredAmount) / physicalItem.Capacity, 0f);

                            if (gasContainer.GasLevel > 1f)
                            {
                                Debug.Fail("Incorrect value");
                            }

                            Character.GetInventory().UpdateGasAmount();

                            bottlesUsed = true;

                            TransferSuitGas(ref gasInfo.Id, transferredAmount, 0);
                            if (gasInfo.FillLevel == 1f)
                            {
                                break;
                            }
                        }
                    }
                    if (bottlesUsed)
                    {
                        if (MySession.Static.LocalCharacter == Character)
                        {
                            ShowRefillFromBottleNotification(gasInfo.Id);
                        }
                        else
                        {
                            Character.SendRefillFromBottle(gasInfo.Id);
                        }
                    }

                    var jetpack = Character.JetpackComp;
                    if (jetpack != null && jetpack.TurnedOn && jetpack.FuelDefinition != null && jetpack.FuelDefinition.Id == gasInfo.Id &&
                        gasInfo.FillLevel <= 0 &&
                        (Character.ControllerInfo.Controller != null && MySession.Static.IsAdminModeEnabled(Character.ControllerInfo.Controller.Player.Id.SteamId) == false || (MySession.Static.LocalCharacter != Character && Sync.IsServer == false)))
                    {
                        jetpack.SwitchThrusts();
                    }
                }
                else
                {
                    gasInfo.NextGasRefill = -1;
                }
            }

            // No oxygen or low oxygen found in room, try to get it from suit
            if (MySession.Static.Settings.EnableOxygen)
            {
                if (noOxygenDamage || lowOxygenDamage)
                {
                    if (HelmetEnabled && SuitOxygenAmount > Definition.OxygenConsumption * Definition.OxygenConsumptionMultiplier)
                    {
                        noOxygenDamage  = false;
                        lowOxygenDamage = false;
                    }

                    if (isInEnvironment && !HelmetEnabled)
                    {
                        if (EnvironmentOxygenLevel > Definition.PressureLevelForLowDamage)
                        {
                            lowOxygenDamage = false;
                        }
                        if (EnvironmentOxygenLevel > 0f)
                        {
                            noOxygenDamage = false;
                        }
                    }
                }

                m_oldSuitOxygenLevel = SuitOxygenLevel;

                if (noOxygenDamage)
                {
                    Character.DoDamage(Definition.DamageAmountAtZeroPressure, MyDamageType.LowPressure, true);
                }
                else if (lowOxygenDamage)
                {
                    Character.DoDamage(1f, MyDamageType.Asphyxia, true);
                }
            }

            Character.UpdateOxygen(SuitOxygenAmount);

            foreach (var gasInfo in m_storedGases)
            {
                Character.UpdateStoredGas(gasInfo.Id, gasInfo.FillLevel);
            }
        }
コード例 #17
0
        public override void UpdateAfterSimulation10()
        {
            base.UpdateAfterSimulation10();

            if (!Sync.IsServer || !IsWorking)
            {
                return;
            }

            if (!ResourceSink.IsPowered)
            {
                if (ResourceSink.IsPowerAvailable(MyResourceDistributorComponent.ElectricityId, BlockDefinition.RequiredPowerInput))
                {
                    float origInput = ResourceSink.RequiredInput;
                    ResourceSink.SetRequiredInputByType(MyResourceDistributorComponent.ElectricityId, 0);
                    ResourceSink.SetRequiredInputByType(MyResourceDistributorComponent.ElectricityId, origInput);
                }
                else
                {
                    return;
                }
            }

            var rotation1 = Quaternion.CreateFromForwardUp(WorldMatrix.Forward, WorldMatrix.Up);
            var position1 = PositionComp.GetPosition() + Vector3D.Transform(PositionComp.LocalVolume.Center + (m_fieldMax.Value + m_fieldMin.Value) * 0.5f, rotation1);

            VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("Recreate Field");
            if (m_recreateField)
            {
                m_recreateField = false;
                m_fieldShape.RemoveReference();
                m_fieldShape = GetHkShape();
                ResourceSink.Update();
            }
            VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();

            var boundingBox = new BoundingBoxD(m_fieldMin.Value, m_fieldMax.Value).Translate(PositionComp.LocalVolume.Center).TransformFast(WorldMatrix.GetOrientation()).Translate(PositionComp.GetPosition());

            m_potentialPenetrations.Clear();
            MyGamePruningStructure.GetTopMostEntitiesInBox(ref boundingBox, m_potentialPenetrations);

            m_potentialVoxelPenetrations.Clear();
            MyGamePruningStructure.GetAllVoxelMapsInBox(ref boundingBox, m_potentialVoxelPenetrations);//disabled until heightmap queries are finished

            VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("Sensor Physics");
            LastDetectedEntity = null;
            bool empty = true;

            foreach (var entity in m_potentialPenetrations)
            {
                if (entity is MyVoxelBase)
                {
                    //voxels are handled in different loop (becaose of planets)
                    continue;
                }
                if (ShouldDetect(entity))
                {
                    Quaternion rotation2;
                    Vector3    posDiff;
                    HkShape?   shape2;
                    if (GetPropertiesFromEntity(entity, ref position1, out rotation2, out posDiff, out shape2))
                    {
                        if (entity.GetPhysicsBody().HavokWorld.IsPenetratingShapeShape(m_fieldShape, ref Vector3.Zero, ref rotation1, shape2.Value, ref posDiff, ref rotation2))
                        {
                            LastDetectedEntity = entity;
                            empty = false;
                            break;
                        }
                    }
                }
            }

            if (DetectAsteroids)
            {
                foreach (var entity in m_potentialVoxelPenetrations)
                {
                    var voxel = entity as MyVoxelPhysics;
                    if (voxel != null)
                    {
                        Vector3D localPositionMin, localPositionMax;

                        MyVoxelCoordSystems.WorldPositionToLocalPosition(boundingBox.Min, voxel.PositionComp.WorldMatrix, voxel.PositionComp.WorldMatrixInvScaled, voxel.SizeInMetresHalf, out localPositionMin);
                        MyVoxelCoordSystems.WorldPositionToLocalPosition(boundingBox.Max, voxel.PositionComp.WorldMatrix, voxel.PositionComp.WorldMatrixInvScaled, voxel.SizeInMetresHalf, out localPositionMax);
                        var aabb = new BoundingBox(localPositionMin, localPositionMax);
                        aabb.Translate(voxel.StorageMin);
                        if (voxel.Storage.Intersect(ref aabb) != ContainmentType.Disjoint)
                        {
                            LastDetectedEntity = voxel;
                            empty = false;
                            break;
                        }
                    }
                    else
                    {
                        Quaternion rotation2;
                        Vector3    posDiff;
                        HkShape?   shape2;
                        if (GetPropertiesFromEntity(entity, ref position1, out rotation2, out posDiff, out shape2))
                        {
                            if (entity.GetPhysicsBody().HavokWorld.IsPenetratingShapeShape(m_fieldShape, ref Vector3.Zero, ref rotation1, shape2.Value, ref posDiff, ref rotation2))
                            {
                                LastDetectedEntity = entity;
                                empty = false;
                                break;
                            }
                        }
                    }
                }
            }
            IsActive = !empty;
            m_potentialPenetrations.Clear();
            m_potentialVoxelPenetrations.Clear();
            VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock();
        }