public override void OnNeighborBlockChanged(int x, int y, int z, int neighborX, int neighborY, int neighborZ) { base.OnNeighborBlockChanged(x, y, z, neighborX, neighborY, neighborZ); WorldSettings worldSettings = m_subsystemGameInfo.WorldSettings; if (worldSettings.EnvironmentBehaviorMode == EnvironmentBehaviorMode.Living && y > 0 && y > worldSettings.TerrainLevel + worldSettings.SeaLevelOffset && (neighborX != x || neighborY != y || neighborZ != z)) { Terrain terrain = SubsystemTerrain.Terrain; if (BlocksManager.Blocks[terrain.GetCellContents(x, y - 1, z)].IsFluidBlocker || BlocksManager.Blocks[terrain.GetCellContents(x, y - 1, z)].IsFluidBlocker) { return; } int i = y; while (i < 128 && Terrain.ExtractContents(terrain.GetCellValue(x, i, z)) == 18) { i++; } SubsystemTerrain.DestroyCell(0, x, i - 1, z, 0, false, false); } }
public void DestroyCell(int toolLevel, int x, int y, int z, int newValue, bool noDrop, bool noParticleSystem) { int cellValue = Terrain.GetCellValue(x, y, z); int num = Terrain.ExtractContents(cellValue); Block block = BlocksManager.Blocks[num]; if (num != 0) { bool showDebris = true; if (!noDrop) { m_dropValues.Clear(); block.GetDropValues(this, cellValue, newValue, toolLevel, m_dropValues, out showDebris); for (int i = 0; i < m_dropValues.Count; i++) { BlockDropValue dropValue = m_dropValues[i]; if (dropValue.Count > 0) { SubsystemBlockBehavior[] blockBehaviors = m_subsystemBlockBehaviors.GetBlockBehaviors(Terrain.ExtractContents(dropValue.Value)); for (int j = 0; j < blockBehaviors.Length; j++) { blockBehaviors[j].OnItemHarvested(x, y, z, cellValue, ref dropValue, ref newValue); } if (dropValue.Count > 0 && Terrain.ExtractContents(dropValue.Value) != 0) { Vector3 position = new Vector3(x, y, z) + new Vector3(0.5f); m_subsystemPickables.AddPickable(dropValue.Value, dropValue.Count, position, null, null); } } } } if (showDebris && !noParticleSystem && m_subsystemViews.CalculateDistanceFromNearestView(new Vector3(x, y, z)) < 16f) { m_subsystemParticles.AddParticleSystem(block.CreateDebrisParticleSystem(this, new Vector3((float)x + 0.5f, (float)y + 0.5f, (float)z + 0.5f), cellValue, 1f)); } } ChangeCell(x, y, z, newValue); }
public bool MovePiston(Point3 position, int length) { Terrain terrain = m_subsystemTerrain.Terrain; int data = Terrain.ExtractData(terrain.GetCellValue(position.X, position.Y, position.Z)); int face = PistonBlock.GetFace(data); PistonMode mode = PistonBlock.GetMode(data); int maxExtension = PistonBlock.GetMaxExtension(data); int pullCount = PistonBlock.GetPullCount(data); int speed = PistonBlock.GetSpeed(data); Point3 point = CellFace.FaceToPoint3(face); length = MathUtils.Clamp(length, 0, maxExtension + 1); int num = 0; m_movingBlocks.Clear(); Point3 offset = point; MovingBlock item; while (m_movingBlocks.Count < 8) { int cellValue = terrain.GetCellValue(position.X + offset.X, position.Y + offset.Y, position.Z + offset.Z); int num2 = Terrain.ExtractContents(cellValue); int face2 = PistonHeadBlock.GetFace(Terrain.ExtractData(cellValue)); if (num2 != 238 || face2 != face) { break; } DynamicArray <MovingBlock> movingBlocks = m_movingBlocks; item = new MovingBlock { Offset = offset, Value = cellValue }; movingBlocks.Add(item); offset += point; num++; } if (length > num) { DynamicArray <MovingBlock> movingBlocks2 = m_movingBlocks; item = new MovingBlock { Offset = Point3.Zero, Value = Terrain.MakeBlockValue(238, 0, PistonHeadBlock.SetFace(PistonHeadBlock.SetMode(PistonHeadBlock.SetIsShaft(0, num > 0), mode), face)) }; movingBlocks2.Add(item); int num3 = 0; while (num3 < 8) { int cellValue2 = terrain.GetCellValue(position.X + offset.X, position.Y + offset.Y, position.Z + offset.Z); if (!IsBlockMovable(cellValue2, face, position.Y + offset.Y, out bool isEnd)) { break; } DynamicArray <MovingBlock> movingBlocks3 = m_movingBlocks; item = new MovingBlock { Offset = offset, Value = cellValue2 }; movingBlocks3.Add(item); num3++; offset += point; if (isEnd) { break; } } if (!IsBlockBlocking(terrain.GetCellValue(position.X + offset.X, position.Y + offset.Y, position.Z + offset.Z))) { GetSpeedAndSmoothness(speed, out float speed2, out Vector2 smoothness); Point3 p = position + (length - num) * point; if (m_subsystemMovingBlocks.AddMovingBlockSet(new Vector3(position) + 0.01f * new Vector3(point), new Vector3(p), speed2, 0f, 0f, smoothness, m_movingBlocks, "Piston", position, testCollision: true) != null) { m_allowPistonHeadRemove = true; try { foreach (MovingBlock movingBlock in m_movingBlocks) { if (movingBlock.Offset != Point3.Zero) { m_subsystemTerrain.ChangeCell(position.X + movingBlock.Offset.X, position.Y + movingBlock.Offset.Y, position.Z + movingBlock.Offset.Z, 0); } } } finally { m_allowPistonHeadRemove = false; } m_subsystemTerrain.ChangeCell(position.X, position.Y, position.Z, Terrain.MakeBlockValue(237, 0, PistonBlock.SetIsExtended(data, isExtended: true))); m_subsystemAudio.PlaySound("Audio/Piston", 1f, 0f, new Vector3(position), 2f, autoDelay: true); } } return(false); } if (length < num) { if (mode != 0) { int num4 = 0; for (int i = 0; i < pullCount + 1; i++) { int cellValue3 = terrain.GetCellValue(position.X + offset.X, position.Y + offset.Y, position.Z + offset.Z); if (!IsBlockMovable(cellValue3, face, position.Y + offset.Y, out bool isEnd2)) { break; } DynamicArray <MovingBlock> movingBlocks4 = m_movingBlocks; item = new MovingBlock { Offset = offset, Value = cellValue3 }; movingBlocks4.Add(item); offset += point; num4++; if (isEnd2) { break; } } if (mode == PistonMode.StrictPulling && num4 < pullCount + 1) { return(false); } } GetSpeedAndSmoothness(speed, out float speed3, out Vector2 smoothness2); float s = (length == 0) ? 0.01f : 0f; Vector3 targetPosition = new Vector3(position) + (length - num) * new Vector3(point) + s * new Vector3(point); if (m_subsystemMovingBlocks.AddMovingBlockSet(new Vector3(position), targetPosition, speed3, 0f, 0f, smoothness2, m_movingBlocks, "Piston", position, testCollision: true) != null) { m_allowPistonHeadRemove = true; try { foreach (MovingBlock movingBlock2 in m_movingBlocks) { m_subsystemTerrain.ChangeCell(position.X + movingBlock2.Offset.X, position.Y + movingBlock2.Offset.Y, position.Z + movingBlock2.Offset.Z, 0); } } finally { m_allowPistonHeadRemove = false; } m_subsystemAudio.PlaySound("Audio/Piston", 1f, 0f, new Vector3(position), 2f, autoDelay: true); } return(false); } return(true); }
public void GenerateGeometry(MovingBlockSet movingBlockSet) { Point3 point = default(Point3); point.X = ((movingBlockSet.CurrentVelocity.X > 0f) ? ((int)MathUtils.Floor(movingBlockSet.Position.X)) : (point.X = (int)MathUtils.Ceiling(movingBlockSet.Position.X))); point.Y = ((movingBlockSet.CurrentVelocity.Y > 0f) ? ((int)MathUtils.Floor(movingBlockSet.Position.Y)) : (point.Y = (int)MathUtils.Ceiling(movingBlockSet.Position.Y))); point.Z = ((movingBlockSet.CurrentVelocity.Z > 0f) ? ((int)MathUtils.Floor(movingBlockSet.Position.Z)) : (point.Z = (int)MathUtils.Ceiling(movingBlockSet.Position.Z))); if (!(point != movingBlockSet.GeometryGenerationPosition)) { return; } Point3 p = new Point3(movingBlockSet.Box.Left, movingBlockSet.Box.Top, movingBlockSet.Box.Near); Point3 point2 = new Point3(movingBlockSet.Box.Width, movingBlockSet.Box.Height, movingBlockSet.Box.Depth); point2.Y = MathUtils.Min(point2.Y, 254); if (m_blockGeometryGenerator == null) { int x = 2; x = (int)MathUtils.NextPowerOf2((uint)x); m_blockGeometryGenerator = new BlockGeometryGenerator(new Terrain(), m_subsystemTerrain, null, base.Project.FindSubsystem <SubsystemFurnitureBlockBehavior>(throwOnError: true), null, base.Project.FindSubsystem <SubsystemPalette>(throwOnError: true)); for (int i = 0; i < x; i++) { for (int j = 0; j < x; j++) { m_blockGeometryGenerator.Terrain.AllocateChunk(i, j); } } } Terrain terrain = m_subsystemTerrain.Terrain; for (int k = 0; k < point2.X + 2; k++) { for (int l = 0; l < point2.Z + 2; l++) { int x2 = k + p.X + point.X - 1; int z = l + p.Z + point.Z - 1; int shaftValue = terrain.GetShaftValue(x2, z); m_blockGeometryGenerator.Terrain.SetTemperature(k, l, Terrain.ExtractTemperature(shaftValue)); m_blockGeometryGenerator.Terrain.SetHumidity(k, l, Terrain.ExtractHumidity(shaftValue)); for (int m = 0; m < point2.Y + 2; m++) { int y = m + p.Y + point.Y - 1; int light = Terrain.ExtractLight(terrain.GetCellValue(x2, y, z)); m_blockGeometryGenerator.Terrain.SetCellValueFast(k, m, l, Terrain.MakeBlockValue(0, light, 0)); } } } m_blockGeometryGenerator.Terrain.SeasonTemperature = terrain.SeasonTemperature; m_blockGeometryGenerator.Terrain.SeasonHumidity = terrain.SeasonHumidity; foreach (MovingBlock block in movingBlockSet.Blocks) { int x3 = block.Offset.X - p.X + 1; int y2 = block.Offset.Y - p.Y + 1; int z2 = block.Offset.Z - p.Z + 1; int value = Terrain.ReplaceLight(light: m_blockGeometryGenerator.Terrain.GetCellLightFast(x3, y2, z2), value: block.Value); m_blockGeometryGenerator.Terrain.SetCellValueFast(x3, y2, z2, value); } m_blockGeometryGenerator.ResetCache(); movingBlockSet.Vertices.Clear(); movingBlockSet.Indices.Clear(); for (int n = 1; n < point2.X + 1; n++) { for (int num = 1; num < point2.Y + 1; num++) { for (int num2 = 1; num2 < point2.Z + 1; num2++) { int cellValueFast = m_blockGeometryGenerator.Terrain.GetCellValueFast(n, num, num2); int num3 = Terrain.ExtractContents(cellValueFast); if (num3 != 0) { BlocksManager.Blocks[num3].GenerateTerrainVertices(m_blockGeometryGenerator, movingBlockSet.Geometry, cellValueFast, n, num, num2); } } } } movingBlockSet.GeometryOffset = new Vector3(p) - new Vector3(1f); movingBlockSet.GeometryGenerationPosition = point; }
public TerrainRaycastResult?Raycast(Vector3 start, Vector3 end, bool useInteractionBoxes, bool skipAirBlocks, Func <int, float, bool> action) { float num = Vector3.Distance(start, end); if (num > 1000f) { Log.Warning("Terrain raycast too long, trimming."); end = start + 1000f * Vector3.Normalize(end - start); } Ray3 ray = new Ray3(start, Vector3.Normalize(end - start)); float x = start.X; float y = start.Y; float z = start.Z; float x2 = end.X; float y2 = end.Y; float z2 = end.Z; int num2 = Terrain.ToCell(x); int num3 = Terrain.ToCell(y); int num4 = Terrain.ToCell(z); int num5 = Terrain.ToCell(x2); int num6 = Terrain.ToCell(y2); int num7 = Terrain.ToCell(z2); int num8 = (x < x2) ? 1 : ((x > x2) ? (-1) : 0); int num9 = (y < y2) ? 1 : ((y > y2) ? (-1) : 0); int num10 = (z < z2) ? 1 : ((z > z2) ? (-1) : 0); float num11 = MathUtils.Floor(x); float num12 = num11 + 1f; float num13 = ((x > x2) ? (x - num11) : (num12 - x)) / Math.Abs(x2 - x); float num14 = MathUtils.Floor(y); float num15 = num14 + 1f; float num16 = ((y > y2) ? (y - num14) : (num15 - y)) / Math.Abs(y2 - y); float num17 = MathUtils.Floor(z); float num18 = num17 + 1f; float num19 = ((z > z2) ? (z - num17) : (num18 - z)) / Math.Abs(z2 - z); float num20 = 1f / Math.Abs(x2 - x); float num21 = 1f / Math.Abs(y2 - y); float num22 = 1f / Math.Abs(z2 - z); while (true) { BoundingBox boundingBox = default(BoundingBox); int collisionBoxIndex = 0; float? num23 = null; int cellValue = Terrain.GetCellValue(num2, num3, num4); int num24 = Terrain.ExtractContents(cellValue); if (num24 != 0 || !skipAirBlocks) { Ray3 ray2 = new Ray3(ray.Position - new Vector3(num2, num3, num4), ray.Direction); int nearestBoxIndex; BoundingBox nearestBox; float? num25 = BlocksManager.Blocks[num24].Raycast(ray2, this, cellValue, useInteractionBoxes, out nearestBoxIndex, out nearestBox); if (num25.HasValue && (!num23.HasValue || num25.Value < num23.Value)) { num23 = num25; collisionBoxIndex = nearestBoxIndex; boundingBox = nearestBox; } } if (num23.HasValue && num23.Value <= num && (action == null || action(cellValue, num23.Value))) { int face = 0; Vector3 vector = start - new Vector3(num2, num3, num4) + num23.Value * ray.Direction; float num26 = float.MaxValue; float num27 = MathUtils.Abs(vector.X - boundingBox.Min.X); if (num27 < num26) { num26 = num27; face = 3; } num27 = MathUtils.Abs(vector.X - boundingBox.Max.X); if (num27 < num26) { num26 = num27; face = 1; } num27 = MathUtils.Abs(vector.Y - boundingBox.Min.Y); if (num27 < num26) { num26 = num27; face = 5; } num27 = MathUtils.Abs(vector.Y - boundingBox.Max.Y); if (num27 < num26) { num26 = num27; face = 4; } num27 = MathUtils.Abs(vector.Z - boundingBox.Min.Z); if (num27 < num26) { num26 = num27; face = 2; } num27 = MathUtils.Abs(vector.Z - boundingBox.Max.Z); if (num27 < num26) { num26 = num27; face = 0; } TerrainRaycastResult value = default(TerrainRaycastResult); value.Ray = ray; value.Value = cellValue; value.CellFace = new CellFace { X = num2, Y = num3, Z = num4, Face = face }; value.CollisionBoxIndex = collisionBoxIndex; value.Distance = num23.Value; return(value); } if (num13 <= num16 && num13 <= num19) { if (num2 == num5) { break; } num13 += num20; num2 += num8; } else if (num16 <= num13 && num16 <= num19) { if (num3 == num6) { break; } num16 += num21; num3 += num9; } else { if (num4 == num7) { break; } num19 += num22; num4 += num10; } } return(null); }