Пример #1
0
        private void UnregisterFromNeighbors()
        {
            // Remove this section from its subscribers
            foreach (var info in Subscribers)
            {
                ChunkEvent subscriber = info;
                if (subscriber == null)
                {
                    continue;
                }

                // Unregistration needs to be done both ways
                subscriber.Register(this, false);
                Register(subscriber, false);
            }
        }
Пример #2
0
        public bool Register(IEventBase <ChunkState> section, bool registerListener)
        {
            // The idea here is to register each neighbor on the main thread. Once a section gathers
            // 4 notifications from its' neighbors chunk generation can be started.

            // Expect the input to be correct
            Assert.IsTrue(section != null);

            // Register
            if (registerListener)
            {
                // Make sure this section is not registered yet
                ChunkEvent newSection     = (ChunkEvent)section;
                int        firstNullIndex = -1;
                for (int i = 0; i < Subscribers.Length; i++)
                {
                    ChunkEvent s = Subscribers[i];
                    if (s == null)
                    {
                        firstNullIndex = i;
                        continue;
                    }

                    if (s == newSection)
                    {
                        return(false);
                    }
                }

                if (firstNullIndex < 0)
                {
                    return(false);
                }

                Assert.IsTrue(section != this, "Trying to register the section to itself");
                Assert.IsTrue(SubscribersCurr < Subscribers.Length, string.Format("ChunkEvent.Register: Condition {0} < {1} not met", SubscribersCurr, Subscribers.Length));

                // New registration, remember the subscriber and increase subscriber count
                Subscribers[firstNullIndex] = (ChunkEvent)section;

                ++SubscribersCurr;
                if (SubscribersCurr != Subscribers.Length)
                {
                    return(false);
                }
            }
            // Unregister
            else
            {
                // Only unregister already registered sections
                int i;
                for (i = 0; i < Subscribers.Length; i++)
                {
                    var item = Subscribers[i];
                    if (item != section)
                    {
                        continue;
                    }

                    break;
                }
                if (i >= Subscribers.Length)
                {
                    return(false);
                }

                Assert.IsTrue(section != this, "Trying to unregister the section from itself");
                Assert.IsTrue(SubscribersCurr > 0, string.Format("ChunkEvent.Unregister: Condition '{0} > 0' not met", SubscribersCurr));

                // Unregister
                --SubscribersCurr;
                Subscribers[i] = null;
                if (SubscribersCurr != 0)
                {
                    return(false);
                }
            }

            OnRegistered(registerListener);
            return(true);
        }
Пример #3
0
        private void QueueSetBlock(Chunk chunk, int bx, int by, int bz, BlockData block)
        {
            // Ignore attempts to change the block into the same one
            if (block.BlockType == Blocks[bx, by, bz].BlockType)
            {
                return;
            }

            int cx = chunk.Pos.X;
            int cy = chunk.Pos.Y;
            int cz = chunk.Pos.Z;

            int subscribersMask = 0;

            // Iterate over neighbors and decide which ones should be notified to rebuild
            for (int i = 0; i < Subscribers.Length; i++)
            {
                ChunkEvent subscriber = Subscribers[i];
                if (subscriber == null)
                {
                    continue;
                }

                Chunk subscriberChunk = (Chunk)subscriber;

                if (subscriberChunk.Pos.X == cx && (
                        // Section to the left
                        ((bx == 0) && (subscriberChunk.Pos.X + 1 == cx)) ||
                        // Section to the right
                        ((bx == EngineSettings.ChunkConfig.Mask) && (subscriberChunk.Pos.X - 1 == cx))
                        ))
                {
                    subscribersMask = subscribersMask | (1 << i);
                }

                if (subscriberChunk.Pos.Y == cy && (
                        // Section to the bottom
                        ((by == 0) && (subscriberChunk.Pos.Y + 1 == cy)) ||
                        // Section to the top
                        ((by == EngineSettings.ChunkConfig.Mask) && (subscriberChunk.Pos.Y - 1 == cy))
                        ))
                {
                    subscribersMask = subscribersMask | (1 << i);
                }

                if (subscriberChunk.Pos.Z == cz && (
                        // Section to the back
                        ((bz == 0) && (subscriberChunk.Pos.Z + 1 == cz)) ||
                        // Section to the front
                        ((bz == EngineSettings.ChunkConfig.Mask) && (subscriberChunk.Pos.Z - 1 == cz))
                        ))
                {
                    subscribersMask = subscribersMask | (1 << i);
                }
            }

            // Request update for the block
            m_setBlockQueue.Add(
                new SetBlockContext(chunk, bx, by, bz, block, subscribersMask)
                );
        }