private static void AssertContainingChunkCoordinates(Vector3Int pos) { Assert.AreEqual( ExpContainingChunkCoordinates(pos), Helpers.ContainingChunkPos(ref pos), pos.ToString() ); }
//returns the position of the chunk containing this block private static Vector3Int ExpContainingChunkCoordinates(Vector3Int pos) { int chunkSize = Env.ChunkSize; int cx = Mathf.FloorToInt(pos.x / (float)chunkSize) * chunkSize; int cy = Mathf.FloorToInt(pos.y / (float)chunkSize) * chunkSize; int cz = Mathf.FloorToInt(pos.z / (float)chunkSize) * chunkSize; return(new Vector3Int(cx, cy, cz)); }
public override void GenerateStructures(Chunk chunk, int layerIndex) { //if (chunk.pos.x!=-30 || chunk.pos.y!=30 || chunk.pos.z!=0) return; int minX = chunk.Pos.x; int maxX = chunk.Pos.x + Env.ChunkSize1; int minZ = chunk.Pos.z; int maxZ = chunk.Pos.z + Env.ChunkSize1; int structureID = 0; for (int x = minX; x <= maxX; x++) { for (int z = minZ; z <= maxZ; z++) { Vector3Int pos = new Vector3Int(x, 0, z); float chanceAtPos = Randomization.RandomPrecise(pos.GetHashCode(), 44); if (chance > chanceAtPos) { if (Randomization.RandomPrecise(pos.Add(1, 0, 0).GetHashCode(), 44) > chanceAtPos && Randomization.RandomPrecise(pos.Add(-1, 0, 0).GetHashCode(), 44) > chanceAtPos && Randomization.RandomPrecise(pos.Add(0, 0, 1).GetHashCode(), 44) > chanceAtPos && Randomization.RandomPrecise(pos.Add(0, 0, -1).GetHashCode(), 44) > chanceAtPos) { int xx = Helpers.Mod(x, Env.ChunkSize); int zz = Helpers.Mod(z, Env.ChunkSize); int height = Helpers.FastFloor(terrainGen.GetTerrainHeightForChunk(chunk, xx, zz)); if (chunk.Pos.y <= height && chunk.Pos.y + Env.ChunkSize1 >= height) { Vector3Int worldPos = new Vector3Int(x, height, z); structure.Build(chunk, structureID++, ref worldPos, this); } } } } } }
public bool RaycastHit(ref Vector3 pos, ref Vector3 dir, ref Vector3Int bPos, bool removalRequested) { return(removalRequested ? Config.raycastHitOnRemoval : Config.raycastHit); }
public virtual void ScheduledUpdate(Chunk chunk, ref Vector3Int localPos) { }
public virtual void RandomUpdate(Chunk chunk, ref Vector3Int localPos) { }
public virtual void OnDestroy(Chunk chunk, ref Vector3Int localPos) { }
public virtual void OnCreate(Chunk chunk, ref Vector3Int localPos) { }
public virtual void BuildBlock(Chunk chunk, ref Vector3Int localpos, int materialID) { }
public void PostProcessChunks() { int minX = m_viewerPos.x - (HorizontalChunkLoadRadius * Env.ChunkSize); int maxX = m_viewerPos.x + (HorizontalChunkLoadRadius * Env.ChunkSize); int minY = m_viewerPos.y - (VerticalChunkLoadRadius * Env.ChunkSize); int maxY = m_viewerPos.y + (VerticalChunkLoadRadius * Env.ChunkSize); int minZ = m_viewerPos.z - (HorizontalChunkLoadRadius * Env.ChunkSize); int maxZ = m_viewerPos.z + (HorizontalChunkLoadRadius * Env.ChunkSize); world.CapCoordXInsideWorld(ref minX, ref maxX); world.CapCoordYInsideWorld(ref minY, ref maxY); world.CapCoordZInsideWorld(ref minZ, ref maxZ); world.Bounds = new AABBInt(minX, minY, minZ, maxX, maxY, maxZ); int expectedChunks = m_chunkPositions.Length * ((maxY - minY + Env.ChunkSize) / Env.ChunkSize); if (// No update necessary if there was no movement m_viewerPos == m_viewerPosPrev && // However, we need to make sure that we have enough chunks loaded world.chunks.Count >= expectedChunks) { return; } // Unregister any non-necessary pending structures Profiler.BeginSample("UnregisterStructures"); { world.UnregisterPendingStructures(); } Profiler.EndSample(); // Cycle through the array of positions Profiler.BeginSample("PostProcessChunks"); { WorldChunks chunks = world.chunks; // Cycle through the array of positions for (int y = maxY; y >= minY; y -= Env.ChunkSize) { for (int i = 0; i < m_chunkPositions.Length; i++) { // Skip loading chunks which are off limits int cx = (m_chunkPositions[i].x * Env.ChunkSize) + m_viewerPos.x; if (cx > maxX || cx < minX) { continue; } int cy = (m_chunkPositions[i].y * Env.ChunkSize) + y; if (cy > maxY || cy < minY) { continue; } int cz = (m_chunkPositions[i].z * Env.ChunkSize) + m_viewerPos.z; if (cz > maxZ || cz < minZ) { continue; } // Create a new chunk if possible Vector3Int newChunkPos = new Vector3Int(cx, cy, cz); Chunk chunk; if (!chunks.CreateOrGetChunk(ref newChunkPos, out chunk)) { continue; } if (FullLoadOnStartUp) { ChunkStateManagerClient stateManager = chunk.stateManager; stateManager.PossiblyVisible = true; stateManager.Visible = false; } m_updateRequests.Add(chunk); } } } Profiler.EndSample(); }
private void UpdateVisibility(int x, int y, int z, int rangeX, int rangeY, int rangeZ) { if (rangeX == 0 || rangeY == 0 || rangeZ == 0) { return; } bool isLast = rangeX == 1 && rangeY == 1 && rangeZ == 1; int wx = m_viewerPos.x + (x * Env.ChunkSize); int wy = m_viewerPos.y + (y * Env.ChunkSize); int wz = m_viewerPos.z + (z * Env.ChunkSize); int rx = rangeX * Env.ChunkSize; int ry = rangeY * Env.ChunkSize; int rz = rangeZ * Env.ChunkSize; // Stop if there is no further subdivision possible if (isLast) { // Update chunk's visibility information Vector3Int chunkPos = new Vector3Int(wx, wy, wz); Chunk chunk = world.chunks.Get(ref chunkPos); if (chunk == null) { return; } ChunkStateManagerClient stateManager = chunk.stateManager; int tx = m_clipmap.TransformX(x); int ty = m_clipmap.TransformY(y); int tz = m_clipmap.TransformZ(z); // Skip chunks which are too far away if (!m_clipmap.IsInsideBounds_Transformed(tx, ty, tz)) { return; } // Update visibility information ClipmapItem item = m_clipmap.Get_Transformed(tx, ty, tz); bool isVisible = Planes.TestPlanesAABB(m_cameraPlanes, chunk.WorldBounds); stateManager.Visible = isVisible && item.IsInVisibleRange; stateManager.PossiblyVisible = isVisible || FullLoadOnStartUp; return; } // Check whether the bouding box lies inside the camera's frustum AABB bounds2 = new AABB(wx, wy, wz, wx + rx, wy + ry, wz + rz); int inside = Planes.TestPlanesAABB2(m_cameraPlanes, bounds2); #region Full invisibility if (inside == 0) { // Full invisibility. All chunks in this area need to be made invisible for (int cy = wy; cy < wy + ry; cy += Env.ChunkSize) { for (int cz = wz; cz < wz + rz; cz += Env.ChunkSize) { for (int cx = wx; cx < wx + rx; cx += Env.ChunkSize) { // Update chunk's visibility information Vector3Int chunkPos = new Vector3Int(cx, cy, cz); Chunk chunk = world.chunks.Get(ref chunkPos); if (chunk == null) { continue; } ChunkStateManagerClient stateManager = chunk.stateManager; // Update visibility information stateManager.PossiblyVisible = FullLoadOnStartUp; stateManager.Visible = false; } } } return; } #endregion #region Full visibility if (inside == 6) { // Full visibility. All chunks in this area need to be made visible for (int cy = wy; cy < wy + ry; cy += Env.ChunkSize) { for (int cz = wz; cz < wz + rz; cz += Env.ChunkSize) { for (int cx = wx; cx < wx + rx; cx += Env.ChunkSize) { // Update chunk's visibility information Vector3Int chunkPos = new Vector3Int(cx, cy, cz); Chunk chunk = world.chunks.Get(ref chunkPos); if (chunk == null) { continue; } ChunkStateManagerClient stateManager = chunk.stateManager; int tx = m_clipmap.TransformX(x); int ty = m_clipmap.TransformY(y); int tz = m_clipmap.TransformZ(z); // Update visibility information ClipmapItem item = m_clipmap.Get_Transformed(tx, ty, tz); stateManager.Visible = item.IsInVisibleRange; stateManager.PossiblyVisible = true; } } } return; } #endregion #region Partial visibility int offX = rangeX; if (rangeX > 1) { offX = rangeX >> 1; rangeX = (rangeX + 1) >> 1; // ceil the number } int offY = rangeY; if (rangeY > 1) { offY = rangeY >> 1; rangeY = (rangeY + 1) >> 1; // ceil the number } int offZ = rangeZ; if (rangeZ > 1) { offZ = rangeZ >> 1; rangeZ = (rangeZ + 1) >> 1; // ceil the number } // Subdivide if possible // TODO: Avoid the recursion UpdateVisibility(x, y, z, offX, offY, offZ); UpdateVisibility(x + offX, y, z, rangeX, offY, offZ); UpdateVisibility(x, y, z + offZ, offX, offY, rangeZ); UpdateVisibility(x + offX, y, z + offZ, rangeX, offY, rangeZ); UpdateVisibility(x, y + offY, z, offX, rangeY, offZ); UpdateVisibility(x + offX, y + offY, z, rangeX, rangeY, offZ); UpdateVisibility(x, y + offY, z + offZ, offX, rangeY, rangeZ); UpdateVisibility(x + offX, y + offY, z + offZ, rangeX, rangeY, rangeZ); #endregion }