Ejemplo n.º 1
0
        private bool IsInGridBounds(Vector3I pos, MyOxygenBlock[, ,] grid)
        {
            if (pos.X < 0 || pos.X >= grid.GetLength(0))
            {
                return(false);
            }
            if (pos.Y < 0 || pos.Y >= grid.GetLength(1))
            {
                return(false);
            }
            if (pos.Z < 0 || pos.Z >= grid.GetLength(2))
            {
                return(false);
            }

            return(true);
        }
Ejemplo n.º 2
0
        private bool ShouldPressurize()
        {
            if (m_cubeGrid.Physics == null)
            {
                return(false);
            }

            if (m_gasBlockCounter > 0 || m_isPressurizing)
            {
                return(true);
            }

            if (m_rooms == null)
            {
                return(false);
            }

            foreach (var room in m_rooms)
            {
                if (room.IsPressurized && room.OxygenAmount > 1f)
                {
                    return(true);
                }

                if (!room.IsPressurized)
                {
                    float deltaTime = MySandboxGame.TotalGamePlayTimeInMilliseconds - room.DepressurizationTime;
                    if (deltaTime < OXYGEN_UNIFORMIZATION_TIME_MS)
                    {
                        return(true);
                    }
                }
            }

            m_rooms    = null;
            m_cubeRoom = null;

            m_prevRooms    = null;
            m_prevCubeRoom = null;

            m_tempPrevRooms    = null;
            m_tempPrevCubeRoom = null;

            return(false);
        }
Ejemplo n.º 3
0
        private void PressurizeInitialize()
        {
            m_tempPrevCubeRoom = m_isPressurizing ? m_prevCubeRoom : m_cubeRoom;
            m_tempPrevRooms    = m_isPressurizing? m_prevRooms : m_rooms;

            Vector3I size = GridMax() - GridMin();

            m_cubeRoom = new MyOxygenBlock[size.X + 1, size.Y + 1, size.Z + 1];
            m_queue.Clear();
            m_queue.Add(new RoomSquare(GridMin(), 0));
            m_tempRooms         = new List <MyOxygenRoom>();
            m_cubeRoom[0, 0, 0] = new MyOxygenBlock(new MyOxygenRoomLink(new MyOxygenRoom(0)));
            m_tempRooms.Add(m_cubeRoom[0, 0, 0].Room);

            m_deletedBlocks.Clear();

            m_queueIndex     = 0;
            m_isPressurizing = true;
        }
Ejemplo n.º 4
0
        private void PressurizePostProcess()
        {
            m_prevCubeRoom = m_tempPrevCubeRoom;
            m_prevRooms    = m_tempPrevRooms;

            for (int i = 0; i < m_cubeRoom.GetLength(0); i++)
            {
                for (int j = 0; j < m_cubeRoom.GetLength(1); j++)
                {
                    for (int k = 0; k < m_cubeRoom.GetLength(2); k++)
                    {
                        var oldRoom = m_cubeRoom[i, j, k];
                        var newRoom = m_tempRooms[m_cubeRoom[i, j, k].Room.Index];

                        m_cubeRoom[i, j, k].RoomLink = newRoom.Link;

                        if (!oldRoom.Room.IsPressurized)
                        {
                            newRoom.IsPressurized        = false;
                            newRoom.EnvironmentOxygen    = Math.Max(newRoom.EnvironmentOxygen, oldRoom.Room.EnvironmentOxygen);
                            newRoom.DepressurizationTime = MySandboxGame.TotalGamePlayTimeInMilliseconds;
                        }

                        newRoom.blockCount++;
                    }
                }
            }

            for (int i = 0; i < m_cubeRoom.GetLength(0); i++)
            {
                for (int j = 0; j < m_cubeRoom.GetLength(1); j++)
                {
                    for (int k = 0; k < m_cubeRoom.GetLength(2); k++)
                    {
                        var room = m_cubeRoom[i, j, k].Room;
                        if (room != null && room.blockCount < 2)
                        {
                            m_cubeRoom[i, j, k].RoomLink = null;
                        }
                    }
                }
            }


            m_rooms = new List <MyOxygenRoom>();
            int index = 0;

            foreach (var room in m_tempRooms)
            {
                if (room.blockCount > 1)
                {
                    room.Index = index;

                    m_rooms.Add(room);
                    index++;
                }
            }

            if (m_savedRooms != null && m_savedRooms.Count() != m_rooms.Count)
            {
                m_savedRooms = null;
            }

            if (m_savedRooms != null)
            {
                for (int i = 0; i < m_rooms.Count; i++)
                {
                    m_rooms[i].OxygenAmount = m_savedRooms[i];
                }
            }
            else
            {
                if (m_prevCubeRoom != null)
                {
                    for (int i = 0; i < m_prevCubeRoom.GetLength(0); i++)
                    {
                        for (int j = 0; j < m_prevCubeRoom.GetLength(1); j++)
                        {
                            for (int k = 0; k < m_prevCubeRoom.GetLength(2); k++)
                            {
                                var prevRoom = m_prevCubeRoom[i, j, k];
                                if (prevRoom.Room == null || prevRoom.Room.blockCount < 2)
                                {
                                    continue;
                                }

                                double cubeOxygen = prevRoom.Room.IsPressurized ? prevRoom.OxygenAmount() : prevRoom.Room.EnvironmentOxygen * GridCubeVolume();// prevRoom.Room.OxygenAmount / prevRoom.Room.blockCount;

                                Vector3I pos = new Vector3I(i, j, k) + m_prevMin - GridMin();

                                if (pos.X < 0 || pos.X >= m_cubeRoom.GetLength(0))
                                {
                                    continue;
                                }
                                if (pos.Y < 0 || pos.Y >= m_cubeRoom.GetLength(1))
                                {
                                    continue;
                                }
                                if (pos.Z < 0 || pos.Z >= m_cubeRoom.GetLength(2))
                                {
                                    continue;
                                }

                                var currentRoom = m_cubeRoom[pos.X, pos.Y, pos.Z].Room;
                                m_cubeRoom[pos.X, pos.Y, pos.Z].PreviousOxygenAmount = (float)cubeOxygen;
                                m_cubeRoom[pos.X, pos.Y, pos.Z].OxygenChangeTime     = MySandboxGame.TotalGamePlayTimeInMilliseconds;

                                if (currentRoom != null && currentRoom.blockCount > 1)
                                {
                                    currentRoom.OxygenAmount += cubeOxygen;
                                }

                                if (currentRoom != null && currentRoom.blockCount < 2)
                                {
                                    m_cubeRoom[pos.X, pos.Y, pos.Z].RoomLink = null;
                                }
                            }
                        }
                    }

                    //Do breach detection in a separate pass to ensure that oxygen levels are correct
                    for (int i = 0; i < m_prevCubeRoom.GetLength(0); i++)
                    {
                        for (int j = 0; j < m_prevCubeRoom.GetLength(1); j++)
                        {
                            for (int k = 0; k < m_prevCubeRoom.GetLength(2); k++)
                            {
                                Vector3I pos = new Vector3I(i, j, k) + m_prevMin - GridMin();
                                if (!IsInGridBounds(pos, m_cubeRoom))
                                {
                                    continue;
                                }

                                var  prevRoom       = m_prevCubeRoom[i, j, k].Room;
                                var  currentRoom    = m_cubeRoom[pos.X, pos.Y, pos.Z].Room;
                                bool breachDetected = false;

                                //Do a preliminary scan to check if there is any new breach
                                for (int l = 0; l < 6; l++)
                                {
                                    Vector3I currNeighbourPos = pos + m_neighbours[l];
                                    if (!IsInGridBounds(currNeighbourPos, m_cubeRoom))
                                    {
                                        continue;
                                    }

                                    Vector3I prevNeighbourPos = new Vector3I(i, j, k) + m_neighbours[l];
                                    if (!IsInGridBounds(prevNeighbourPos, m_prevCubeRoom))
                                    {
                                        continue;
                                    }

                                    var currNeighbourRoom = m_cubeRoom[currNeighbourPos.X, currNeighbourPos.Y, currNeighbourPos.Z].Room;
                                    var prevNeighbourRoom = m_prevCubeRoom[prevNeighbourPos.X, prevNeighbourPos.Y, prevNeighbourPos.Z].Room;

                                    if (currNeighbourRoom == currentRoom && prevNeighbourRoom != prevRoom)
                                    {
                                        breachDetected = true;
                                    }
                                }

                                float    minOxygenLevel = float.MaxValue;
                                float    maxOxygenLevel = float.MinValue;
                                Vector3I minPos         = Vector3I.Zero;
                                if (breachDetected)
                                {
                                    //Scan to determine if there is actually a difference in pressure levels
                                    for (int l = 0; l < 6; l++)
                                    {
                                        Vector3I currNeighbourPos = pos + m_neighbours[l];
                                        if (!IsInGridBounds(currNeighbourPos, m_cubeRoom))
                                        {
                                            continue;
                                        }

                                        Vector3I prevNeighbourPos = new Vector3I(i, j, k) + m_neighbours[l];
                                        if (!IsInGridBounds(prevNeighbourPos, m_prevCubeRoom))
                                        {
                                            continue;
                                        }

                                        var prevNeighbourRoom = m_prevCubeRoom[prevNeighbourPos.X, prevNeighbourPos.Y, prevNeighbourPos.Z].Room;
                                        if (prevNeighbourRoom == null)
                                        {
                                            continue;
                                        }

                                        if (IsPressurized(pos + GridMin(), currNeighbourPos + GridMin()))
                                        {
                                            continue;
                                        }

                                        float level = prevNeighbourRoom.IsPressurized ? prevNeighbourRoom.OxygenLevel(m_cubeGrid.GridSize) : prevNeighbourRoom.EnvironmentOxygen;

                                        if (level > maxOxygenLevel)
                                        {
                                            maxOxygenLevel = level;
                                        }
                                        if (level < minOxygenLevel)
                                        {
                                            minOxygenLevel = level;
                                            minPos         = currNeighbourPos;
                                        }
                                    }
                                }

                                if (maxOxygenLevel - minOxygenLevel > 0.2f)
                                {
                                    Vector3D from = m_cubeGrid.GridIntegerToWorld(pos + GridMin());
                                    Vector3D to   = m_cubeGrid.GridIntegerToWorld(minPos + GridMin());

                                    AddDepressurizationEffects(from, to);
                                }
                            }
                        }
                    }
                }

                ApplyDepressurizationForces();

                foreach (var room in m_rooms)
                {
                    if (room.OxygenLevel(m_cubeGrid.GridSize) > 1.0)
                    {
                        room.OxygenAmount = room.MaxOxygen(m_cubeGrid.GridSize);
                    }
                }
            }

            m_prevMin        = GridMin();
            m_isPressurizing = false;
            m_queueIndex     = 0;
        }
        private void PressurizeInitialize()
        {
            m_tempPrevCubeRoom = isPressurizing ? m_prevCubeRoom : m_cubeRoom;
            m_tempPrevRooms = isPressurizing? m_prevRooms : m_rooms;

            Vector3I size = GridMax() - GridMin();

            m_cubeRoom = new MyOxygenBlock[size.X + 1, size.Y + 1, size.Z + 1];
            m_queue.Clear();
            m_queue.Add(new RoomSquare(GridMin(), 0));
            m_tempRooms = new List<MyOxygenRoom>();
            m_cubeRoom[0, 0, 0] = new MyOxygenBlock(new MyOxygenRoom(0));
            m_tempRooms.Add(m_cubeRoom[0, 0, 0].Room);

            m_queueIndex = 0;
            isPressurizing = true;
        }
        private void PressurizePostProcess()
        {
            m_prevCubeRoom = m_tempPrevCubeRoom;
            m_prevRooms = m_tempPrevRooms;

            for (int i = 0; i < m_cubeRoom.GetLength(0); i++)
                for (int j = 0; j < m_cubeRoom.GetLength(1); j++)
                    for (int k = 0; k < m_cubeRoom.GetLength(2); k++)
                    {
                        var oldRoom = m_cubeRoom[i, j, k];
                        var newRoom = m_tempRooms[m_cubeRoom[i, j, k].Room.Index];

                        m_cubeRoom[i, j, k].Room = newRoom;

                        if (!oldRoom.Room.IsPressurized)
                        {
                            newRoom.IsPressurized = false;
                            newRoom.EnvironmentOxygen = Math.Max(newRoom.EnvironmentOxygen, oldRoom.Room.EnvironmentOxygen);
                            newRoom.DepressurizationTime = MySandboxGame.TotalGamePlayTimeInMilliseconds;
                        }

                        Vector3I current = new Vector3I(i, j, k) + GridMin();

                        newRoom.blockCount++;
                    }

            for (int i = 0; i < m_cubeRoom.GetLength(0); i++)
                for (int j = 0; j < m_cubeRoom.GetLength(1); j++)
                    for (int k = 0; k < m_cubeRoom.GetLength(2); k++)
                    {
                        var room = m_cubeRoom[i, j, k].Room;
                        if (room != null && room.blockCount < 2)
                        {
                            m_cubeRoom[i, j, k].Room = null;
                        }
                    }


            m_rooms = new List<MyOxygenRoom>();
            int index = 0;
            foreach (var room in m_tempRooms)
            {
                if (room.blockCount > 1)
                {
                    room.Index = index;

                    m_rooms.Add(room);
                    index++;
                }
            }

            if (m_savedRooms != null && m_savedRooms.Count() != m_rooms.Count)
            {
                m_savedRooms = null;
            }

            if (m_savedRooms != null)
            {
                for (int i = 0; i < m_rooms.Count; i++)
                {
                    m_rooms[i].OxygenAmount = m_savedRooms[i];
                }
            }
            else
            {
                if (m_prevCubeRoom != null)
                {
                    for (int i = 0; i < m_prevCubeRoom.GetLength(0); i++)
                        for (int j = 0; j < m_prevCubeRoom.GetLength(1); j++)
                            for (int k = 0; k < m_prevCubeRoom.GetLength(2); k++)
                            {
                                var prevRoom = m_prevCubeRoom[i, j, k];
                                if (prevRoom.Room == null || prevRoom.Room.blockCount < 2)
                                    continue;

                                double cubeOxygen = prevRoom.Room.IsPressurized ? prevRoom.OxygenAmount() : prevRoom.Room.EnvironmentOxygen * GridCubeVolume();// prevRoom.Room.OxygenAmount / prevRoom.Room.blockCount;

                                Vector3I pos = new Vector3I(i, j, k) + m_prevMin - GridMin();

                                if (pos.X < 0 || pos.X >= m_cubeRoom.GetLength(0))
                                    continue;
                                if (pos.Y < 0 || pos.Y >= m_cubeRoom.GetLength(1))
                                    continue;
                                if (pos.Z < 0 || pos.Z >= m_cubeRoom.GetLength(2))
                                    continue;
                                
                                var currentRoom = m_cubeRoom[pos.X, pos.Y, pos.Z].Room;
                                m_cubeRoom[pos.X, pos.Y, pos.Z].PreviousOxygenAmount = (float)cubeOxygen;
                                m_cubeRoom[pos.X, pos.Y, pos.Z].OxygenChangeTime = MySandboxGame.TotalGamePlayTimeInMilliseconds;

                                if (currentRoom != null && currentRoom.blockCount > 1)
                                {
                                    currentRoom.OxygenAmount += cubeOxygen;
                                }

                                if (currentRoom != null && currentRoom.blockCount < 2)
                                {
                                    m_cubeRoom[pos.X, pos.Y, pos.Z].Room = null;
                                }
                            }

                    //Do breach detection in a separate pass to ensure that oxygen levels are correct
                    for (int i = 0; i < m_prevCubeRoom.GetLength(0); i++)
                        for (int j = 0; j < m_prevCubeRoom.GetLength(1); j++)
                            for (int k = 0; k < m_prevCubeRoom.GetLength(2); k++)
                            {
                                Vector3I pos = new Vector3I(i, j, k) + m_prevMin - GridMin();
                                if (!IsInGridBounds(pos, m_cubeRoom))
                                    continue;

                                var prevRoom = m_prevCubeRoom[i, j, k].Room;
                                var currentRoom = m_cubeRoom[pos.X, pos.Y, pos.Z].Room;
                                bool breachDetected = false;

                                //Do a preliminary scan to check if there is any new breach
                                for (int l = 0; l < 6; l++)
                                {
                                    Vector3I currNeighbourPos = pos + m_neighbours[l];
                                    if (!IsInGridBounds(currNeighbourPos, m_cubeRoom))
                                        continue;

                                    Vector3I prevNeighbourPos = new Vector3I(i, j, k) + m_neighbours[l];
                                    if (!IsInGridBounds(prevNeighbourPos, m_prevCubeRoom))
                                        continue;

                                    var currNeighbourRoom = m_cubeRoom[currNeighbourPos.X, currNeighbourPos.Y, currNeighbourPos.Z].Room;
                                    var prevNeighbourRoom = m_prevCubeRoom[prevNeighbourPos.X, prevNeighbourPos.Y, prevNeighbourPos.Z].Room;

                                    if (currNeighbourRoom == currentRoom && prevNeighbourRoom != prevRoom)
                                    {
                                        breachDetected = true;
                                    }
                                }

                                float minOxygenLevel = float.MaxValue;
                                float maxOxygenLevel = float.MinValue;
                                Vector3I minPos = Vector3I.Zero;
                                if (breachDetected)
                                {
                                    //Scan to determine if there is actually a difference in pressure levels
                                    for (int l = 0; l < 6; l++)
                                    {
                                        Vector3I currNeighbourPos = pos + m_neighbours[l];
                                        if (!IsInGridBounds(currNeighbourPos, m_cubeRoom))
                                            continue;

                                        Vector3I prevNeighbourPos = new Vector3I(i, j, k) + m_neighbours[l];
                                        if (!IsInGridBounds(prevNeighbourPos, m_prevCubeRoom))
                                            continue;

                                        var prevNeighbourRoom = m_prevCubeRoom[prevNeighbourPos.X, prevNeighbourPos.Y, prevNeighbourPos.Z].Room;
                                        if (prevNeighbourRoom == null)
                                            continue;

                                        if (IsPressurized(pos + GridMin(), currNeighbourPos + GridMin()))
                                            continue;

                                        float level = prevNeighbourRoom.IsPressurized ? prevNeighbourRoom.OxygenLevel(m_cubeGrid.GridSize) : prevNeighbourRoom.EnvironmentOxygen;

                                        if (level > maxOxygenLevel)
                                        {
                                            maxOxygenLevel = level;
                                        }
                                        if (level < minOxygenLevel)
                                        {
                                            minOxygenLevel = level;
                                            minPos = currNeighbourPos;
                                        }
                                    }
                                }

                                if (maxOxygenLevel - minOxygenLevel > 0.2f)
                                {
                                    Vector3D from = m_cubeGrid.GridIntegerToWorld(pos + GridMin());
                                    Vector3D to = m_cubeGrid.GridIntegerToWorld(minPos + GridMin());

                                    //Force
                                    float MAX_DISTANCE = 5f;

                                    var boundingSphere = new BoundingSphereD(to, MAX_DISTANCE);
                                    var decompressionDirection = Vector3D.Normalize(to - from);
                                    MyGamePruningStructure.GetAllEntitiesInSphere<MyEntity>(ref boundingSphere, m_entitiesInDepressurizationRange);

                                    foreach (var entity in m_entitiesInDepressurizationRange)
                                    {
                                        if (!(entity is MyCubeBlock) && !(entity is MyEntitySubpart) && entity.Physics != null)
                                        {
                                            var entityPos = entity.PositionComp.WorldMatrix.Translation;

                                            var forceDirection = (to - from) / 2f;
                                            var distance = (to - entityPos).Length();
                                            if (distance < MAX_DISTANCE)
                                            {
                                                forceDirection /= distance;

                                                if (Vector3D.Dot(decompressionDirection, forceDirection) < 0f)
                                                {
                                                    forceDirection = -forceDirection;
                                                }

                                                //float forceStrength = 500f * prevRoom.Room.OxygenLevel(m_cubeGrid.GridSize) * (1f - (float)distance / MAX_DISTANCE);
                                                float forceStrength = 500f * (1f - (float)distance / MAX_DISTANCE);

                                                MyDepressurizationForceInfo forceInfo;
                                                if (!m_forcesToApply.TryGetValue(entity, out forceInfo))
                                                {
                                                    forceInfo = new MyDepressurizationForceInfo();

                                                    forceInfo.Direction = forceDirection;
                                                    forceInfo.Strength = forceStrength;
                                                    forceInfo.ForceCount = 1;
                                                }
                                                else
                                                {
                                                    forceInfo.Direction = (forceInfo.Direction * forceInfo.ForceCount + forceDirection) / (forceInfo.ForceCount + 1);
                                                    forceInfo.Strength = (forceInfo.Strength * forceInfo.ForceCount + forceStrength) / (forceInfo.ForceCount + 1);
                                                    forceInfo.ForceCount++;
                                                }

                                                m_forcesToApply[entity] = forceInfo;
                                            }
                                        }
                                    }

                                    m_entitiesInDepressurizationRange.Clear();

                                    //Effect
                                    MyParticleEffect m_effect;
                                    if (MyParticlesManager.TryCreateParticleEffect(49, out m_effect))
                                    {
                                        var orientation = Matrix.CreateFromDir(to - from);
                                        orientation.Translation = from;
                                        m_effect.UserScale = 3f;

                                        m_effect.WorldMatrix = orientation;
                                        m_effect.AutoDelete = true;

                                        m_depressurizationEffects.Add(m_effect);
                                    }
                                }
                            }
                }

                foreach (var force in m_forcesToApply)
                {
                    var entity = force.Key;
                    var forceInfo = force.Value;

                    var character = entity as Sandbox.Game.Entities.Character.MyCharacter;
                    if (character != null)
                    {
                        if (character.Parent != null)
                        {
                            continue;
                        }
                        forceInfo.Strength *= 5f;
                    }

                    if (forceInfo.Strength > 1f)
                    {
                        if (character != null && character.IsDead == false)
                        {
                            character.EnableJetpack(true);
                        }

                        forceInfo.Direction.Normalize();
                        entity.Physics.AddForce(MyPhysicsForceType.APPLY_WORLD_IMPULSE_AND_WORLD_ANGULAR_IMPULSE, forceInfo.Direction * forceInfo.Strength, entity.PositionComp.WorldMatrix.Translation, null);
                    }
                }

                m_forcesToApply.Clear();

                foreach (var room in m_rooms)
                {
                    if (room.OxygenLevel(m_cubeGrid.GridSize) > 1.0)
                    {
                        room.OxygenAmount = room.MaxOxygen(m_cubeGrid.GridSize);
                    }

                }
            }

            m_prevMin = GridMin();
            isPressurizing = false;
            m_queueIndex = 0;
        }
        private bool ShouldPressurize()
        {
            if (m_cubeGrid.Physics == null)
            {
                return false;
            }

            if (m_oxygenBlocks.Count > 0)
            {
                return true;
            }

            if (isPressurizing)
            {
                return true;
            }

            if (m_rooms != null)
            {
                foreach (var room in m_rooms)
                {
                    if (room.IsPressurized && room.OxygenAmount > 1f)
                    {
                        return true;
                    }

                    if (!room.IsPressurized)
                    {
                        float deltaTime = MySandboxGame.TotalGamePlayTimeInMilliseconds - room.DepressurizationTime;
                        if (deltaTime < OXYGEN_UNIFORMIZATION_TIME_MS)
                        {
                            return true;
                        }
                    }
                }

                m_rooms = null;
                m_cubeRoom = null;

                m_prevRooms = null;
                m_prevCubeRoom = null;

                m_tempPrevRooms = null;
                m_tempPrevCubeRoom = null;
            }

            return false;
        }
Ejemplo n.º 8
0
        private void PressurizePostProcess()
        {
            m_prevCubeRoom = m_tempPrevCubeRoom;
            m_prevRooms = m_tempPrevRooms;

            for (int i = 0; i < m_cubeRoom.GetLength(0); i++)
                for (int j = 0; j < m_cubeRoom.GetLength(1); j++)
                    for (int k = 0; k < m_cubeRoom.GetLength(2); k++)
                    {
                        var oldRoom = m_cubeRoom[i, j, k];
                        var newRoom = m_tempRooms[m_cubeRoom[i, j, k].Room.Index];

                        m_cubeRoom[i, j, k].RoomLink = newRoom.Link;

                        if (!oldRoom.Room.IsPressurized)
                        {
                            newRoom.IsPressurized = false;
                            newRoom.EnvironmentOxygen = Math.Max(newRoom.EnvironmentOxygen, oldRoom.Room.EnvironmentOxygen);
                            newRoom.DepressurizationTime = MySandboxGame.TotalGamePlayTimeInMilliseconds;
                        }

                        Vector3I current = new Vector3I(i, j, k) + GridMin();

                        newRoom.blockCount++;
                    }

            for (int i = 0; i < m_cubeRoom.GetLength(0); i++)
                for (int j = 0; j < m_cubeRoom.GetLength(1); j++)
                    for (int k = 0; k < m_cubeRoom.GetLength(2); k++)
                    {
                        var room = m_cubeRoom[i, j, k].Room;
                        if (room != null && room.blockCount < 2)
                        {
                            m_cubeRoom[i, j, k].RoomLink = null;
                        }
                    }


            m_rooms = new List<MyOxygenRoom>();
            int index = 0;
            foreach (var room in m_tempRooms)
            {
                if (room.blockCount > 1)
                {
                    room.Index = index;

                    m_rooms.Add(room);
                    index++;
                }
            }

            if (m_savedRooms != null && m_savedRooms.Count() != m_rooms.Count)
            {
                m_savedRooms = null;
            }

            if (m_savedRooms != null)
            {
                for (int i = 0; i < m_rooms.Count; i++)
                {
                    m_rooms[i].OxygenAmount = m_savedRooms[i];
                }
            }
            else
            {
                if (m_prevCubeRoom != null)
                {
                    for (int i = 0; i < m_prevCubeRoom.GetLength(0); i++)
                        for (int j = 0; j < m_prevCubeRoom.GetLength(1); j++)
                            for (int k = 0; k < m_prevCubeRoom.GetLength(2); k++)
                            {
                                var prevRoom = m_prevCubeRoom[i, j, k];
                                if (prevRoom.Room == null || prevRoom.Room.blockCount < 2)
                                    continue;

                                double cubeOxygen = prevRoom.Room.IsPressurized ? prevRoom.OxygenAmount() : prevRoom.Room.EnvironmentOxygen * GridCubeVolume();// prevRoom.Room.OxygenAmount / prevRoom.Room.blockCount;

                                Vector3I pos = new Vector3I(i, j, k) + m_prevMin - GridMin();

                                if (pos.X < 0 || pos.X >= m_cubeRoom.GetLength(0))
                                    continue;
                                if (pos.Y < 0 || pos.Y >= m_cubeRoom.GetLength(1))
                                    continue;
                                if (pos.Z < 0 || pos.Z >= m_cubeRoom.GetLength(2))
                                    continue;
                                
                                var currentRoom = m_cubeRoom[pos.X, pos.Y, pos.Z].Room;
                                m_cubeRoom[pos.X, pos.Y, pos.Z].PreviousOxygenAmount = (float)cubeOxygen;
                                m_cubeRoom[pos.X, pos.Y, pos.Z].OxygenChangeTime = MySandboxGame.TotalGamePlayTimeInMilliseconds;

                                if (currentRoom != null && currentRoom.blockCount > 1)
                                {
                                    currentRoom.OxygenAmount += cubeOxygen;
                                }

                                if (currentRoom != null && currentRoom.blockCount < 2)
                                {
                                    m_cubeRoom[pos.X, pos.Y, pos.Z].RoomLink = null;
                                }
                            }

                    //Do breach detection in a separate pass to ensure that oxygen levels are correct
                    for (int i = 0; i < m_prevCubeRoom.GetLength(0); i++)
                        for (int j = 0; j < m_prevCubeRoom.GetLength(1); j++)
                            for (int k = 0; k < m_prevCubeRoom.GetLength(2); k++)
                            {
                                Vector3I pos = new Vector3I(i, j, k) + m_prevMin - GridMin();
                                if (!IsInGridBounds(pos, m_cubeRoom))
                                    continue;

                                var prevRoom = m_prevCubeRoom[i, j, k].Room;
                                var currentRoom = m_cubeRoom[pos.X, pos.Y, pos.Z].Room;
                                bool breachDetected = false;

                                //Do a preliminary scan to check if there is any new breach
                                for (int l = 0; l < 6; l++)
                                {
                                    Vector3I currNeighbourPos = pos + m_neighbours[l];
                                    if (!IsInGridBounds(currNeighbourPos, m_cubeRoom))
                                        continue;

                                    Vector3I prevNeighbourPos = new Vector3I(i, j, k) + m_neighbours[l];
                                    if (!IsInGridBounds(prevNeighbourPos, m_prevCubeRoom))
                                        continue;

                                    var currNeighbourRoom = m_cubeRoom[currNeighbourPos.X, currNeighbourPos.Y, currNeighbourPos.Z].Room;
                                    var prevNeighbourRoom = m_prevCubeRoom[prevNeighbourPos.X, prevNeighbourPos.Y, prevNeighbourPos.Z].Room;

                                    if (currNeighbourRoom == currentRoom && prevNeighbourRoom != prevRoom)
                                    {
                                        breachDetected = true;
                                    }
                                }

                                float minOxygenLevel = float.MaxValue;
                                float maxOxygenLevel = float.MinValue;
                                Vector3I minPos = Vector3I.Zero;
                                if (breachDetected)
                                {
                                    //Scan to determine if there is actually a difference in pressure levels
                                    for (int l = 0; l < 6; l++)
                                    {
                                        Vector3I currNeighbourPos = pos + m_neighbours[l];
                                        if (!IsInGridBounds(currNeighbourPos, m_cubeRoom))
                                            continue;

                                        Vector3I prevNeighbourPos = new Vector3I(i, j, k) + m_neighbours[l];
                                        if (!IsInGridBounds(prevNeighbourPos, m_prevCubeRoom))
                                            continue;

                                        var prevNeighbourRoom = m_prevCubeRoom[prevNeighbourPos.X, prevNeighbourPos.Y, prevNeighbourPos.Z].Room;
                                        if (prevNeighbourRoom == null)
                                            continue;

                                        if (IsPressurized(pos + GridMin(), currNeighbourPos + GridMin()))
                                            continue;

                                        float level = prevNeighbourRoom.IsPressurized ? prevNeighbourRoom.OxygenLevel(m_cubeGrid.GridSize) : prevNeighbourRoom.EnvironmentOxygen;

                                        if (level > maxOxygenLevel)
                                        {
                                            maxOxygenLevel = level;
                                        }
                                        if (level < minOxygenLevel)
                                        {
                                            minOxygenLevel = level;
                                            minPos = currNeighbourPos;
                                        }
                                    }
                                }

                                if (maxOxygenLevel - minOxygenLevel > 0.2f)
                                {
                                    Vector3D from = m_cubeGrid.GridIntegerToWorld(pos + GridMin());
                                    Vector3D to = m_cubeGrid.GridIntegerToWorld(minPos + GridMin());

                                    AddDepressurizationEffects(from, to);
                                }
                            }
                }

                ApplyDepressurizationForces();

                foreach (var room in m_rooms)
                {
                    if (room.OxygenLevel(m_cubeGrid.GridSize) > 1.0)
                    {
                        room.OxygenAmount = room.MaxOxygen(m_cubeGrid.GridSize);
                    }

                }
            }

            m_prevMin = GridMin();
            isPressurizing = false;
            m_queueIndex = 0;
        }
        private void PressurizePostProcess()
        {
            // No need to post-process when closing
            if (isClosing) return;

            ProfilerShort.Begin("Oxygen PressurizePostProcess");
            m_prevCubeRoom = m_tempPrevCubeRoom;
            m_prevCubeRoomDimensions = m_tempPrevCubeRoomDimensions;
            m_prevRooms = m_tempPrevRooms;

            ProfilerShort.Begin("DeallocateAllMarked");
            m_OxygenRoomLinkPool.pool.DeallocateAllMarked();
            ProfilerShort.End();

            ProfilerShort.Begin("Block 1");
            for (int i = 0; i < m_cubeRoomDimensions.X; i++)
                for (int j = 0; j < m_cubeRoomDimensions.Y; j++)
                    for (int k = 0; k < m_cubeRoomDimensions.Z; k++)
                    {
                        MyOxygenBlock cubeRoom = m_cubeRoom[i, j, k];
                        var newRoom = m_tempRooms[cubeRoom.Room.Index];

                        m_cubeRoom[i, j, k].RoomLink = newRoom.Link;

                        if (!cubeRoom.Room.IsPressurized)
                        {
                            newRoom.IsPressurized = false;
                            newRoom.EnvironmentOxygen = Math.Max(newRoom.EnvironmentOxygen, cubeRoom.Room.EnvironmentOxygen);
                            newRoom.DepressurizationTime = MySandboxGame.TotalGamePlayTimeInMilliseconds;
                        }

                        newRoom.blockCount++;
                    }
            ProfilerShort.End();
            ProfilerShort.Begin("Block 2");
            for (int i = 0; i < m_cubeRoomDimensions.X; i++)
                for (int j = 0; j < m_cubeRoomDimensions.Y; j++)
                    for (int k = 0; k < m_cubeRoomDimensions.Z; k++)
                    {
                        var room = m_cubeRoom[i, j, k].Room;
                        if (room != null && room.blockCount < 2)
                        {
                            m_cubeRoom[i, j, k].RoomLink = null;
                        }
                    }
            ProfilerShort.End();

            ProfilerShort.Begin("Block 3");
            m_rooms = new List<MyOxygenRoom>();
            int index = 0;
            foreach (var room in m_tempRooms)
            {
                if (room.blockCount > 1)
                {
                    room.Index = index;

                    m_rooms.Add(room);
                    index++;
                }
            }

            if (m_savedRooms != null && m_savedRooms.Length != m_rooms.Count)
            {
                m_savedRooms = null;
            }
            ProfilerShort.End();

            ProfilerShort.Begin("Block 4");
            if (m_savedRooms != null)
            {
                for (int i = 0; i < m_rooms.Count; i++)
                {
                    m_rooms[i].OxygenAmount = m_savedRooms[i];
                }
            }
            else
            {
                if (m_prevCubeRoom != null)
                {
                    ProfilerShort.Begin("Block 4 A");
                    for (int i = 0; i < m_prevCubeRoomDimensions.X; i++)
                        for (int j = 0; j < m_prevCubeRoomDimensions.Y; j++)
                            for (int k = 0; k < m_prevCubeRoomDimensions.Z; k++)
                            {
                                var prevRoom = m_prevCubeRoom[i, j, k];
                                if (prevRoom.Room == null || prevRoom.Room.blockCount < 2)
                                    continue;

                                double cubeOxygen = prevRoom.Room.IsPressurized ? prevRoom.OxygenAmount() : prevRoom.Room.EnvironmentOxygen * GridCubeVolume();// prevRoom.Room.OxygenAmount / prevRoom.Room.blockCount;

                                Vector3I pos = new Vector3I(i, j, k) + m_prevMin - GridMin();

                                if (!IsInGridBounds(ref pos, ref m_cubeRoomDimensions))
                                    continue;
                                
                                var currentRoom = m_cubeRoom[pos.X, pos.Y, pos.Z].Room;
                                m_cubeRoom[pos.X, pos.Y, pos.Z].PreviousOxygenAmount = (float)cubeOxygen;
                                m_cubeRoom[pos.X, pos.Y, pos.Z].OxygenChangeTime = MySandboxGame.TotalGamePlayTimeInMilliseconds;

                                if (currentRoom != null && currentRoom.blockCount > 1)
                                {
                                    currentRoom.OxygenAmount += cubeOxygen;
                                }

                                if (currentRoom != null && currentRoom.blockCount < 2)
                                {
                                    m_cubeRoom[pos.X, pos.Y, pos.Z].RoomLink = null;
                                }
                            }
                    ProfilerShort.End();

                    ProfilerShort.Begin("Block 4 B");
                    //Do breach detection in a separate pass to ensure that oxygen levels are correct
                    for (int i = 0; i < m_prevCubeRoomDimensions.X; i++)
                        for (int j = 0; j < m_prevCubeRoomDimensions.Y; j++)
                            for (int k = 0; k < m_prevCubeRoomDimensions.Z; k++)
                            {
                                Vector3I pos = new Vector3I(i, j, k) + m_prevMin - GridMin();
                                if (!IsInGridBounds(ref pos, ref m_cubeRoomDimensions))
                                    continue;

                                var prevRoom = m_prevCubeRoom[i, j, k].Room;
                                var currentRoom = m_cubeRoom[pos.X, pos.Y, pos.Z].Room;
                                bool breachDetected = false;

                                //Do a preliminary scan to check if there is any new breach
                                for (int l = 0; l < 6; l++)
                                {
                                    Vector3I currNeighbourPos = pos + m_neighbours[l];
                                    if (!IsInGridBounds(ref currNeighbourPos, ref m_cubeRoomDimensions))
                                        continue;

                                    Vector3I prevNeighbourPos = new Vector3I(i, j, k) + m_neighbours[l];
                                    if (!IsInGridBounds(ref prevNeighbourPos, ref m_prevCubeRoomDimensions))
                                        continue;

                                    var currNeighbourRoom = m_cubeRoom[currNeighbourPos.X, currNeighbourPos.Y, currNeighbourPos.Z].Room;
                                    var prevNeighbourRoom = m_prevCubeRoom[prevNeighbourPos.X, prevNeighbourPos.Y, prevNeighbourPos.Z].Room;

                                    if (currNeighbourRoom == currentRoom && prevNeighbourRoom != prevRoom)
                                    {
                                        breachDetected = true;
                                    }
                                }

                                float minOxygenLevel = float.MaxValue;
                                float maxOxygenLevel = float.MinValue;
                                Vector3I minPos = Vector3I.Zero;
                                if (breachDetected)
                                {
                                    //Scan to determine if there is actually a difference in pressure levels
                                    for (int l = 0; l < 6; l++)
                                    {
                                        Vector3I currNeighbourPos = pos + m_neighbours[l];
                                        if (!IsInGridBounds(ref currNeighbourPos, ref m_cubeRoomDimensions))
                                            continue;

                                        Vector3I prevNeighbourPos = new Vector3I(i, j, k) + m_neighbours[l];
                                        if (!IsInGridBounds(ref prevNeighbourPos, ref m_prevCubeRoomDimensions))
                                            continue;

                                        var prevNeighbourRoom = m_prevCubeRoom[prevNeighbourPos.X, prevNeighbourPos.Y, prevNeighbourPos.Z].Room;
                                        if (prevNeighbourRoom == null)
                                            continue;

                                        if (IsPressurized(pos + GridMin(), currNeighbourPos + GridMin()))
                                            continue;

                                        float level = prevNeighbourRoom.IsPressurized ? prevNeighbourRoom.OxygenLevel(m_cubeGrid.GridSize) : prevNeighbourRoom.EnvironmentOxygen;

                                        if (level > maxOxygenLevel)
                                        {
                                            maxOxygenLevel = level;
                                        }
                                        if (level < minOxygenLevel)
                                        {
                                            minOxygenLevel = level;
                                            minPos = currNeighbourPos;
                                        }
                                    }
                                }

                                if (maxOxygenLevel - minOxygenLevel > 0.2f)
                                {
                                    Vector3D from = m_cubeGrid.GridIntegerToWorld(pos + GridMin());
                                    Vector3D to = m_cubeGrid.GridIntegerToWorld(minPos + GridMin());

                                    AddDepressurizationEffects(from, to);
                                }
                            }
                    ProfilerShort.End();
                }

                ProfilerShort.Begin("Block 4 C");
                ApplyDepressurizationForces();
                ProfilerShort.End();

                ProfilerShort.Begin("Block 4 D");
                foreach (var room in m_rooms)
                {
                    if (room.OxygenLevel(m_cubeGrid.GridSize) > 1.0)
                    {
                        room.OxygenAmount = room.MaxOxygen(m_cubeGrid.GridSize);
                    }

                }
                ProfilerShort.End();
            }
            ProfilerShort.End();

            m_prevMin = GridMin();
            m_isPressurizing = false;
            ProfilerShort.End();
        }
        private void PressurizeInitialize()
        {
            if (!m_isPressurizing)
            {
                m_tempPrevCubeRoom = m_cubeRoom;
                m_tempPrevCubeRoomDimensions = m_cubeRoomDimensions;
                m_tempPrevRooms = m_rooms;
            }

            Vector3I size = GridMax() - GridMin();

            // Only allocate new m_cubeRoom if the grid size changes
            Vector3I newRoomDimensions = size + Vector3I.One;
            //if (m_cubeRoom == null || newRoomDimensions.X != m_cubeRoomDimensions.X || newRoomDimensions.Y != m_cubeRoomDimensions.Y || newRoomDimensions.Z != m_cubeRoomDimensions.Z)
            {
                m_cubeRoom = new MyOxygenBlock[newRoomDimensions.X, newRoomDimensions.Y, newRoomDimensions.Z];
                m_cubeRoomDimensions = newRoomDimensions;
            }
            /*else
            {
                // Reset the grid instead
                for (int i = 0; i < m_cubeRoomDimensions.X; i++)
                {
                    for (int j = 0; j < m_cubeRoomDimensions.Y; j++)
                    {
                        for (int k = 0; k < m_cubeRoomDimensions.Z; k++)
                        {
                            m_cubeRoom[i, j, k].Reset();
                        }
                    }
                }
            }*/

            if (m_OxygenRoomLinkPool == null)
                m_OxygenRoomLinkPool = new MyOxygenRoomLinkPool(2 * (size.X + 1) * (size.Y + 1) * (size.Z + 1) + 10);
            else
            {
                ProfilerShort.Begin("MarkAllActiveForDeallocate");
                m_OxygenRoomLinkPool.pool.MarkAllActiveForDeallocate();
                ProfilerShort.End();
            }
            m_queue.Clear();
            m_qMaxSize = 0;
            m_roomCnt = 0;
            m_storedGridMin = GridMin();
            m_storedGridMax = GridMax();
            m_queue.Enqueue(new RoomSquare(GridMin(), 0));
            m_tempRooms = new List<MyOxygenRoom>();
            MyOxygenRoomLink link = m_OxygenRoomLinkPool.get();
            link.SetRoom(new MyOxygenRoom(0));
            m_cubeRoom[0, 0, 0].SetDefaults(link);
            //m_cubeRoom[0, 0, 0] = new MyOxygenBlock(new MyOxygenRoomLink(new MyOxygenRoom(0)));
            m_tempRooms.Add(m_cubeRoom[0, 0, 0].Room);

            m_deletedBlocks.Clear();
            
            m_isPressurizing = true;
        }
        private bool ShouldPressurize()
        {
            if (m_cubeGrid.Physics == null)
                return false;

            if (m_gasBlockCounter > 0 || m_isPressurizing)
                return true;

	        if (m_rooms == null)
		        return false;

            for (int roomIndex = 0; roomIndex < m_rooms.Count; roomIndex++)
            {
                MyOxygenRoom room = m_rooms[roomIndex];

                if (room.IsPressurized && room.OxygenAmount > 1f)
			        return true;

                // If it is not pressurized, check if enough time elapsed since it was changed to prevent too-early depressurization
		        if (!room.IsPressurized)
		        {
			        float deltaTime = MySandboxGame.TotalGamePlayTimeInMilliseconds - room.DepressurizationTime;
			        if (deltaTime < OXYGEN_UNIFORMIZATION_TIME_MS)
				        return true;
		        }
	        }

            // Grid is no longer pressurized, clear out data
            // TODO: Performance optimization! This is probably a bad idea!
	        m_rooms = null;
	        m_cubeRoom = null;
            m_cubeRoomDimensions = Vector3I.Zero;

	        m_prevRooms = null;
	        m_prevCubeRoom = null;
            m_prevCubeRoomDimensions = Vector3I.Zero;

	        m_tempPrevRooms = null;
	        m_tempPrevCubeRoom = null;
            m_tempPrevCubeRoomDimensions = Vector3I.Zero;

	        return false;
        }