示例#1
0
            public void Output(DrawOpBlock b)
            {
                if (b.Block == Block.Invalid)
                {
                    return;
                }
                Level  lvl = op.Level;
                Player p   = op.Player;

                if (b.X >= lvl.Width || b.Y >= lvl.Height || b.Z >= lvl.Length)
                {
                    return;
                }

                int     index = b.X + lvl.Width * (b.Z + b.Y * lvl.Length);
                BlockID old   = lvl.blocks[index];

                #if TEN_BIT_BLOCKS
                BlockID extended = Block.ExtendedBase[old];
                if (extended > 0)
                {
                    old = (BlockID)(extended | lvl.FastGetExtTile(b.X, b.Y, b.Z));
                }
                #else
                if (old == Block.custom_block)
                {
                    old = (BlockID)(Block.Extended | lvl.FastGetExtTile(b.X, b.Y, b.Z));
                }
                #endif

                if (old == Block.Invalid)
                {
                    return;
                }
                // Check to make sure the block is actually different and that can be used
                if (old == b.Block || !p.group.Blocks[old] || !p.group.Blocks[b.Block])
                {
                    return;
                }

                // Check if player can affect block at coords in world
                AccessController denied = lvl.CanAffect(p, b.X, b.Y, b.Z);
                if (denied != null)
                {
                    if (p.lastAccessStatus < DateTime.UtcNow)
                    {
                        denied.CheckDetailed(p);
                        p.lastAccessStatus = DateTime.UtcNow.AddSeconds(2);
                    }
                    return;
                }

                // Set the block (inlined)
                lvl.Changed = true;
                if (b.Block >= Block.Extended)
                {
                    #if TEN_BIT_BLOCKS
                    lvl.blocks[index] = Block.ExtendedClass[b.Block >> Block.ExtendedShift];
                    #else
                    lvl.blocks[index] = Block.custom_block;
                    #endif
                    lvl.FastSetExtTile(b.X, b.Y, b.Z, (BlockRaw)b.Block);
                }
                else
                {
                    lvl.blocks[index] = (BlockRaw)b.Block;
                    if (old >= Block.Extended)
                    {
                        lvl.FastRevertExtTile(b.X, b.Y, b.Z);
                    }
                }

                lvl.BlockDB.Cache.Add(p, b.X, b.Y, b.Z, op.Flags, old, b.Block);
                p.SessionModified++; p.TotalModified++; p.TotalDrawn++; // increment block stats inline

                // Potentially buffer the block change
                if (op.TotalModified == reloadThreshold)
                {
                    if (!p.Ignores.DrawOutput)
                    {
                        p.Message("Changed over {0} blocks, preparing to reload map..", reloadThreshold);
                    }
                    lvl.blockqueue.ClearAll();
                }
                else if (op.TotalModified < reloadThreshold)
                {
                    if (!Block.VisuallyEquals(old, b.Block))
                    {
                        lvl.blockqueue.Add(p, index, b.Block);
                    }

                    if (lvl.physics > 0)
                    {
                        if (old == Block.Sponge && b.Block != Block.Sponge)
                        {
                            OtherPhysics.DoSpongeRemoved(lvl, index, false);
                        }
                        if (old == Block.LavaSponge && b.Block != Block.LavaSponge)
                        {
                            OtherPhysics.DoSpongeRemoved(lvl, index, true);
                        }

                        if (lvl.ActivatesPhysics(b.Block))
                        {
                            lvl.AddCheck(index);
                        }
                    }
                }
                op.TotalModified++;


                // Attempt to prevent BlockDB in-memory cache from growing too large (> 1,000,000 entries)
                int count = lvl.BlockDB.Cache.Count;
                if (count == 0 || (count % 1000000) != 0)
                {
                    return;
                }

                // if drawop has a read lock on BlockDB (e.g. undo/redo), we must release it here
                bool hasReadLock = false;
                if (op.BlockDBReadLock != null)
                {
                    op.BlockDBReadLock.Dispose();
                    hasReadLock = true;
                }

                using (IDisposable wLock = lvl.BlockDB.Locker.AccquireWrite(100)) {
                    if (wLock != null)
                    {
                        lvl.BlockDB.FlushCache();
                    }
                }

                if (!hasReadLock)
                {
                    return;
                }
                op.BlockDBReadLock = lvl.BlockDB.Locker.AccquireRead();
            }
示例#2
0
            public void Output(DrawOpBlock b)
            {
                if (b.Block.BlockID == Block.Invalid)
                {
                    return;
                }
                Level  lvl = op.Level;
                Player p   = op.Player;

                if (b.X >= lvl.Width || b.Y >= lvl.Height || b.Z >= lvl.Length)
                {
                    return;
                }

                int      index = b.X + lvl.Width * (b.Z + b.Y * lvl.Length);
                ExtBlock old;

                old.BlockID = lvl.blocks[index]; old.ExtID = 0;
                if (old.BlockID == Block.custom_block)
                {
                    old.ExtID = lvl.GetExtTileNoCheck(b.X, b.Y, b.Z);
                }
                if (old.BlockID == Block.Invalid)
                {
                    return;
                }

                // Check to make sure the block is actually different and that we can change it
                if (old == b.Block || !lvl.CheckAffectPermissions(p, b.X, b.Y, b.Z, old, b.Block))
                {
                    return;
                }

                // Set the block (inlined)
                lvl.blocks[index] = b.Block.BlockID;
                lvl.Changed       = true;
                if (old.BlockID == Block.custom_block && b.Block.BlockID != Block.custom_block)
                {
                    lvl.RevertExtTileNoCheck(b.X, b.Y, b.Z);
                }
                if (b.Block.BlockID == Block.custom_block)
                {
                    lvl.SetExtTileNoCheck(b.X, b.Y, b.Z, b.Block.ExtID);
                }

                if (p != null)
                {
                    lvl.BlockDB.Cache.Add(p, b.X, b.Y, b.Z, op.Flags, old, b.Block);
                    p.SessionModified++; p.TotalModified++; p.TotalDrawn++; // increment block stats inline
                }

                // Potentially buffer the block change
                if (op.TotalModified == reloadThreshold)
                {
                    if (p == null || !p.Ignores.DrawOutput)
                    {
                        Player.Message(p, "Changed over {0} blocks, preparing to reload map..", reloadThreshold);
                    }

                    lock (lvl.queueLock)
                        lvl.blockqueue.Clear();
                }
                else if (op.TotalModified < reloadThreshold)
                {
                    if (!old.VisuallyEquals(b.Block))
                    {
                        BlockQueue.Addblock(p, index, b.Block);
                    }

                    if (lvl.physics > 0)
                    {
                        if (old.BlockID == Block.Sponge && b.Block.BlockID != Block.Sponge)
                        {
                            OtherPhysics.DoSpongeRemoved(lvl, index, false);
                        }
                        if (old.BlockID == Block.LavaSponge && b.Block.BlockID != Block.LavaSponge)
                        {
                            OtherPhysics.DoSpongeRemoved(lvl, index, true);
                        }

                        if (lvl.ActivatesPhysics(b.Block))
                        {
                            lvl.AddCheck(index);
                        }
                    }
                }
                op.TotalModified++;


                // Attempt to prevent the BlockDB from growing too large (> 1,000,000 entries)
                int count = lvl.BlockDB.Cache.Count;

                if (count == 0 || (count % 1000000) != 0)
                {
                    return;
                }

                // if drawop has a read lock on BlockDB (e.g. undo/redo), we must release it here
                bool hasReadLock = false;

                if (op.BlockDBReadLock != null)
                {
                    op.BlockDBReadLock.Dispose();
                    hasReadLock = true;
                }

                using (IDisposable wLock = lvl.BlockDB.Locker.AccquireWrite(100)) {
                    if (wLock != null)
                    {
                        lvl.BlockDB.WriteEntries();
                    }
                }

                if (!hasReadLock)
                {
                    return;
                }
                op.BlockDBReadLock = lvl.BlockDB.Locker.AccquireRead();
            }