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); } }
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); }
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) ); }