public void ProcessSetBlockQueue() { // Modify blocks for (int i = 0; i < m_setBlockQueue.Count; i++) { SetBlockContext context = m_setBlockQueue[i]; Blocks[context.BX, context.BY, context.BZ] = context.Block; // Chunk needs to be finialized again /* * TODO: This can be optimized. There's no need to recompute min/max chunk index * everytime we update a block. An update is only required when we delete/add a block. * The best would be having two 2D [chunkWidth,chunkHeight] arrays storing min and * max height indexes respectively. This would be helpful for other things as well. */ RefreshState(ChunkState.FinalizeData); // Let us know that there was a change in data since the last time the chunk // was loaded so we can enqueue serialization only when it is really necessary. m_refreshTasks = m_refreshTasks.Set(ChunkState.Serialize); // Ask for rebuild of geometry RefreshState(ChunkState.BuildVertices); // Notify subscribers if (context.SubscribersMask > 0) { for (int j = 0; j < Subscribers.Length; j++) { Chunk subscriber = (Chunk)Subscribers[j]; if (subscriber != null && ((context.SubscribersMask >> j) & 1) != 0) { subscriber.RefreshState(ChunkState.BuildVertices); } } } } m_setBlockQueue.Clear(); }
private void ProcessSetBlockQueue() { if (m_setBlockQueue.Count <= 0) { return; } StateManager.RequestState(ChunkState.FinalizeData | ChunkState.BuildVerticesNow); int rebuildMask = 0; // Modify blocks for (int j = 0; j < m_setBlockQueue.Count; j++) { SetBlockContext context = m_setBlockQueue[j]; int x, y, z; Helpers.GetIndex3DFrom1D(context.Index, out x, out y, out z); this[x, y, z] = context.Block; if ( // Only check neighbors if it is still needed rebuildMask == 0x3f || // Only check neighbors when it is a change of a block on a chunk's edge (((x + 1) & EngineSettings.ChunkConfig.Mask) > 1 && ((y + 1) & EngineSettings.ChunkConfig.Mask) > 1 && ((z + 1) & EngineSettings.ChunkConfig.Mask) > 1) ) { continue; } int cx = Pos.X; int cy = Pos.Y; int cz = Pos.Z; // If it is an edge position, notify neighbor as well // Iterate over neighbors and decide which ones should be notified to rebuild for (int i = 0; i < StateManager.Listeners.Length; i++) { ChunkEvent listener = StateManager.Listeners[i]; if (listener == null) { continue; } // No further checks needed once we know all neighbors need to be notified if (rebuildMask == 0x3f) { break; } ChunkStateManagerClient listenerChunk = (ChunkStateManagerClient)listener; int lx = listenerChunk.chunk.Pos.X; int ly = listenerChunk.chunk.Pos.Y; int lz = listenerChunk.chunk.Pos.Z; if ((ly == cy || lz == cz) && ( // Section to the left ((x == 0) && (lx + EngineSettings.ChunkConfig.Mask == cx)) || // Section to the right ((x == EngineSettings.ChunkConfig.Mask) && (lx - EngineSettings.ChunkConfig.Mask == cx)) )) { rebuildMask = rebuildMask | (1 << i); } if ((lx == cx || lz == cz) && ( // Section to the bottom ((y == 0) && (ly + EngineSettings.ChunkConfig.Mask == cy)) || // Section to the top ((y == EngineSettings.ChunkConfig.Mask) && (ly - EngineSettings.ChunkConfig.Mask == cy)) )) { rebuildMask = rebuildMask | (1 << i); } if ((ly == cy || lx == cx) && ( // Section to the back ((z == 0) && (lz + EngineSettings.ChunkConfig.Mask == cz)) || // Section to the front ((z == EngineSettings.ChunkConfig.Mask) && (lz - EngineSettings.ChunkConfig.Mask == cz)) )) { rebuildMask = rebuildMask | (1 << i); } } } m_setBlockQueue.Clear(); // Notify neighbors that they need to rebuilt their geometry if (rebuildMask > 0) { for (int j = 0; j < StateManager.Listeners.Length; j++) { ChunkStateManagerClient listener = (ChunkStateManagerClient)StateManager.Listeners[j]; if (listener != null && ((rebuildMask >> j) & 1) != 0) { listener.RequestState(ChunkState.FinalizeData | ChunkState.BuildVerticesNow); } } } }