Пример #1
0
        public void Update()
        {
            ChunkStateManagerClient stateManager = (ChunkStateManagerClient)chunk.stateManager;

            if (m_setBlockQueue.Count > 0)
            {
                if (rebuildMaskGeometry < 0)
                {
                    rebuildMaskGeometry = 0;
                }
                if (rebuildMaskCollider < 0)
                {
                    rebuildMaskCollider = 0;
                }

                // Modify blocks
                for (int j = 0; j < m_setBlockQueue.Count; j++)
                {
                    SetBlockContext context = m_setBlockQueue[j];

                    int x, y, z;
                    Helpers.GetChunkIndex3DFrom1D(context.Index, out x, out y, out z);

                    Vector3Int pos       = new Vector3Int(x, y, z);
                    Vector3Int globalPos = pos + chunk.pos;

                    BlockData oldBlockData = blocks.Get(context.Index);

                    Block oldBlock = m_blockTypes[oldBlockData.Type];
                    Block newBlock = m_blockTypes[context.Block.Type];
                    oldBlock.OnDestroy(chunk, pos, globalPos);
                    newBlock.OnCreate(chunk, pos, globalPos);

                    blocks.Set(context.Index, context.Block);

                    if (context.SetBlockModified)
                    {
                        BlockModified(new BlockPos(x, y, z), globalPos, context.Block);

                        chunk.blocks.contentsInvalidated = true;
                    }

                    if (
                        // Only check neighbors if it is still needed
                        rebuildMaskGeometry == 0x3f ||
                        // Only check neighbors when it is a change of a block on a chunk's edge
                        (((pos.x + 1) & Env.ChunkMask) > 1 &&
                         ((pos.y + 1) & Env.ChunkMask) > 1 &&
                         ((pos.z + 1) & Env.ChunkMask) > 1)
                        )
                    {
                        continue;
                    }

                    int cx = chunk.pos.x;
                    int cy = chunk.pos.y;
                    int cz = chunk.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 (rebuildMaskGeometry == 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
                                ((pos.x == 0) && (lx + Env.ChunkSize == cx)) ||
                                // Section to the right
                                ((pos.x == Env.ChunkMask) && (lx - Env.ChunkSize == cx))
                            ))
                        {
                            rebuildMaskGeometry = rebuildMaskGeometry | (1 << i);
                        }

                        if ((lx == cx || lz == cz) &&
                            (
                                // Section to the bottom
                                ((pos.y == 0) && (ly + Env.ChunkSize == cy)) ||
                                // Section to the top
                                ((pos.y == Env.ChunkMask) && (ly - Env.ChunkSize == cy))
                            ))
                        {
                            rebuildMaskGeometry = rebuildMaskGeometry | (1 << i);
                        }

                        if ((ly == cy || lx == cx) &&
                            (
                                // Section to the back
                                ((pos.z == 0) && (lz + Env.ChunkSize == cz)) ||
                                // Section to the front
                                ((pos.z == Env.ChunkMask) && (lz - Env.ChunkSize == cz))
                            ))
                        {
                            rebuildMaskGeometry = rebuildMaskGeometry | (1 << i);
                        }
                    }

                    rebuildMaskCollider |= rebuildMaskGeometry;
                }

                m_setBlockQueue.Clear();
            }

            long now = Globals.Watch.ElapsedMilliseconds;

            // Request a geometry update at most 10 times a second
            if (rebuildMaskGeometry >= 0 && now - lastUpdateTimeGeometry >= 100)
            {
                lastUpdateTimeGeometry = now;

                // Request rebuild on this chunk
                stateManager.RequestState(ChunkState.BuildVerticesNow);;

                // Notify neighbors that they need to rebuilt their geometry
                if (rebuildMaskGeometry > 0)
                {
                    for (int j = 0; j < stateManager.Listeners.Length; j++)
                    {
                        ChunkStateManagerClient listener = (ChunkStateManagerClient)stateManager.Listeners[j];
                        if (listener != null && ((rebuildMaskGeometry >> j) & 1) != 0)
                        {
                            // Request rebuild on neighbor chunks
                            listener.RequestState(ChunkState.BuildVerticesNow);
                        }
                    }
                }

                rebuildMaskGeometry = -1;
            }

            // Request a collider update at most 4 times a second
            if (chunk.NeedsCollider && rebuildMaskCollider >= 0 && now - lastUpdateTimeCollider >= 250)
            {
                lastUpdateTimeCollider = now;

                // Request rebuild on this chunk
                stateManager.RequestState(ChunkState.BuildCollider);

                // Notify neighbors that they need to rebuilt their geometry
                if (rebuildMaskCollider > 0)
                {
                    for (int j = 0; j < stateManager.Listeners.Length; j++)
                    {
                        ChunkStateManagerClient listener = (ChunkStateManagerClient)stateManager.Listeners[j];
                        if (listener != null && ((rebuildMaskCollider >> j) & 1) != 0)
                        {
                            // Request rebuild on neighbor chunks
                            if (listener.chunk.NeedsCollider)
                            {
                                listener.RequestState(ChunkState.BuildCollider);
                            }
                        }
                    }
                }

                rebuildMaskCollider = -1;
            }
        }
Пример #2
0
        public void Update()
        {
            ChunkStateManagerClient stateManager = (ChunkStateManagerClient)chunk.stateManager;

            if (m_setBlockQueue.Count > 0)
            {
                if (rebuildMaskGeometry < 0)
                {
                    rebuildMaskGeometry = 0;
                }
                if (rebuildMaskCollider < 0)
                {
                    rebuildMaskCollider = 0;
                }

                // Modify blocks
                for (int j = 0; j < m_setBlockQueue.Count; j++)
                {
                    SetBlockContext context = m_setBlockQueue[j];

                    if (!context.IsRange())
                    {
                        ProcessSetBlockQueue(context.Block, context.IndexFrom, context.SetBlockModified);
                    }
                    else
                    {
                        int sx, sy, sz, ex, ey, ez;
                        Helpers.GetChunkIndex3DFrom1D(context.IndexFrom, out sx, out sy, out sz);
                        Helpers.GetChunkIndex3DFrom1D(context.IndexTo, out ex, out ey, out ez);

                        for (int y = sy; y <= ey; y++)
                        {
                            for (int z = sz; z <= ez; z++)
                            {
                                for (int x = sx; x <= ex; x++)
                                {
                                    int index = Helpers.GetChunkIndex1DFrom3D(x, y, z);
                                    ProcessSetBlockQueue(context.Block, index, context.SetBlockModified);
                                }
                            }
                        }
                    }
                }

                rebuildMaskCollider |= rebuildMaskGeometry;

                m_setBlockQueue.Clear();
            }

            long now = Globals.Watch.ElapsedMilliseconds;

            // Request a geometry update at most 10 times a second
            if (rebuildMaskGeometry >= 0 && now - lastUpdateTimeGeometry >= 100)
            {
                lastUpdateTimeGeometry = now;

                // Request rebuild on this chunk
                stateManager.RequestState(ChunkState.BuildVerticesNow);;

                // Notify neighbors that they need to rebuilt their geometry
                if (rebuildMaskGeometry > 0)
                {
                    for (int j = 0; j < stateManager.Listeners.Length; j++)
                    {
                        ChunkStateManagerClient listener = (ChunkStateManagerClient)stateManager.Listeners[j];
                        if (listener != null && ((rebuildMaskGeometry >> j) & 1) != 0)
                        {
                            // Request rebuild on neighbor chunks
                            listener.RequestState(ChunkState.BuildVerticesNow);
                        }
                    }
                }

                rebuildMaskGeometry = -1;
            }

            // Request a collider update at most 4 times a second
            if (chunk.NeedsCollider && rebuildMaskCollider >= 0 && now - lastUpdateTimeCollider >= 250)
            {
                lastUpdateTimeCollider = now;

                // Request rebuild on this chunk
                stateManager.RequestState(ChunkState.BuildCollider);

                // Notify neighbors that they need to rebuilt their geometry
                if (rebuildMaskCollider > 0)
                {
                    for (int j = 0; j < stateManager.Listeners.Length; j++)
                    {
                        ChunkStateManagerClient listener = (ChunkStateManagerClient)stateManager.Listeners[j];
                        if (listener != null && ((rebuildMaskCollider >> j) & 1) != 0)
                        {
                            // Request rebuild on neighbor chunks
                            if (listener.chunk.NeedsCollider)
                            {
                                listener.RequestState(ChunkState.BuildCollider);
                            }
                        }
                    }
                }

                rebuildMaskCollider = -1;
            }
        }