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); }
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); }
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; }
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; }
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; }