/// <summary> /// Applies the damage to affected chunks. /// </summary> /// <param name="damage">Damage.</param> private void ApplyDamage(List <IntPoint> damage) { long minX = long.MaxValue, minY = long.MaxValue, maxX = long.MinValue, maxY = long.MinValue; for (int i = 0; i < damage.Count; ++i) { if (damage[i].X < minX) { minX = damage[i].X; } if (damage[i].X > maxX) { maxX = damage[i].X; } if (damage[i].Y < minY) { minY = damage[i].Y; } if (damage[i].Y > maxY) { maxY = damage[i].Y; } } minX = Helper.NegDivision(minX, Chunk.SIZE); maxX = Helper.NegDivision(maxX, Chunk.SIZE); minY = Helper.NegDivision(minY, Chunk.SIZE); maxY = Helper.NegDivision(maxY, Chunk.SIZE); var clipper = new Clipper(); for (int y = (int)minY; y <= maxY; ++y) { for (int x = (int)minX; x <= maxX; ++x) { var chunk = GetChunk(TerrainHelper.PackCoordinates(x, y)); clipper.Clear(); clipper.AddPolygon(new List <IntPoint>() { new IntPoint(chunk.Left, chunk.Top), new IntPoint(chunk.Left + Chunk.SIZE, chunk.Top), new IntPoint(chunk.Left + Chunk.SIZE, chunk.Top + Chunk.SIZE), new IntPoint(chunk.Left, chunk.Top + Chunk.SIZE) }, PolyType.ptSubject); clipper.AddPolygon(damage, PolyType.ptClip); clipper.AddPolygons(chunk.Damage, PolyType.ptClip); clipper.Execute(ClipType.ctIntersection, chunk.Damage, PolyFillType.pftNonZero, PolyFillType.pftNonZero); chunk.Recalculate = true; if (ActiveChunks.Contains(chunk)) { Task.Run(() => { PlaceChunk(chunk); }); } } } }
/// <summary> /// Sets a region around a point as active. /// </summary> /// <param name="center">Center.</param> public override void SetActiveArea(Vector2 center) { _activeX = Helper.NegDivision((int)center.X, Chunk.SIZE); _activeY = Helper.NegDivision((int)center.Y, Chunk.SIZE); Chunk[] newActive = new Chunk[CHUNK_CACHE * CHUNK_CACHE]; for (int y = 0; y < CHUNK_CACHE; ++y) { for (int x = 0; x < CHUNK_CACHE; ++x) { var cX = x + _activeX - CHUNK_CACHE / 2; var cY = y + _activeY - CHUNK_CACHE / 2; var id = TerrainHelper.PackCoordinates(cX, cY); Chunk chunk = null; if (ActiveChunks.Any(c => c != null && c.ID == id)) { chunk = ActiveChunks.First(c => c != null && c.ID == id); } else { chunk = GetChunk(id); if (Multithreaded) { Task.Run(() => { PlaceChunk(chunk); }); } else { PlaceChunk(chunk); } } newActive[x + y * CHUNK_CACHE] = chunk; } } for (int i = 0; i < ActiveChunks.Length; ++i) { if (ActiveChunks[i] != null && !newActive.Contains(ActiveChunks[i])) { UnplaceChunk(ActiveChunks[i]); if (!ActiveChunks[i].ShouldSave) { ChunkCache.Remove(ActiveChunks[i].ID); } } } ActiveChunks = newActive; }
public Chunk(int x, int y) : this(TerrainHelper.PackCoordinates(x, y)) { }
/// <summary> /// Get the ID of a chunk at a given position. /// </summary> /// <returns>ID.</returns> /// <param name="x">The x coordinate.</param> /// <param name="y">The y coordinate.</param> public ulong ChunkID(float x, float y) { return(TerrainHelper.PackCoordinates(Helper.NegDivision((int)x, Chunk.SIZE), Helper.NegDivision((int)y, Chunk.SIZE))); }