Exemple #1
0
        void OutputBlock(DrawOpBlock b, DrawOpOutput output)
        {
            int dx = (b.X - P.X) * signX, dy = (b.Y - P.Y) * signY, dz = (b.Z - P.Z) * signZ;

            int begX = P.X + dx * XMul / XDiv, endX = P.X + (dx + dirX) * XMul / XDiv;
            int begY = P.Y + dy * YMul / YDiv, endY = P.Y + (dy + dirY) * YMul / YDiv;
            int begZ = P.Z + dz * ZMul / ZDiv, endZ = P.Z + (dz + dirZ) * ZMul / ZDiv;

            // Scale out until we hit the next block
            for (int y = begY; y != endY; y += dirY)
            {
                for (int z = begZ; z != endZ; z += dirZ)
                {
                    for (int x = begX; x != endX; x += dirX)
                    {
                        if (x < 0 || y < 0 || z < 0 || x >= width || y >= height || z >= length)
                        {
                            continue;
                        }
                        b.X = (ushort)x; b.Y = (ushort)y; b.Z = (ushort)z;
                        output(b);
                    }
                }
            }
        }
Exemple #2
0
        void OutputBlock(DrawOpBlock b, DrawOpOutput output)
        {
            double dx = b.X - P.X, dy = b.Y - P.Y, dz = b.Z - P.Z;
            double rotX = 0, rotY = 0, rotZ = 0;

            // Rotate X
            rotY = cosX * dy - sinX * dz;
            rotZ = sinX * dy + cosX * dz;
            dy   = rotY; dz = rotZ;

            // Rotate Y
            rotX = cosY * dx + sinY * dz;
            rotZ = -sinY * dx + cosY * dz;
            dx   = rotX; dz = rotZ;

            // Rotate Z
            rotX = cosZ * dx - sinZ * dy;
            rotY = sinZ * dx + cosZ * dy;
            dx   = rotX; dy = rotY;

            b.X = (ushort)(dx + P.X + ((dx % 1) >= 0.5 ? 1 : 0));
            b.Y = (ushort)(dy + P.Y + ((dy % 1) >= 0.5 ? 1 : 0));
            b.Z = (ushort)(dz + P.Z + ((dz % 1) >= 0.5 ? 1 : 0));
            output(b);
        }
        static void OutputBlock(DrawOpBlock b, DrawOp op)
        {
            if (b.Block == Block.Invalid)
            {
                return;
            }
            Level  lvl = op.Level;
            Player p = op.Player;
            byte   old = lvl.GetTile(b.X, b.Y, b.Z), oldExt = 0;

            if (old == Block.custom_block)
            {
                oldExt = lvl.GetExtTile(b.X, b.Y, b.Z);
            }

            if (op.TotalModified > Server.DrawReloadLimit)
            {
                if (old == Block.Invalid)
                {
                    return;
                }
                bool same = old == b.Block;
                if (same && b.Block == Block.custom_block)
                {
                    same = lvl.GetExtTile(b.X, b.Y, b.Z) == b.ExtBlock;
                }
                if (same || !lvl.CheckAffectPermissions(p, b.X, b.Y, b.Z, old, b.Block, b.ExtBlock))
                {
                    return;
                }

                lvl.SetTile(b.X, b.Y, b.Z, b.Block, p, b.ExtBlock, op.Flags);
                p.IncrementBlockStats(b.Block, true);
            }
            else if (op.TotalModified == Server.DrawReloadLimit)
            {
                Player.Message(p, "Affected over {0} blocks, prepared to reload map..", Server.DrawReloadLimit);
                lock (lvl.queueLock)
                    lvl.blockqueue.Clear();
            }
            else
            {
                if (!lvl.DoBlockchange(p, b.X, b.Y, b.Z, b.Block, b.ExtBlock, true))
                {
                    return;
                }

                lvl.BlockDB.Add(p, b.X, b.Y, b.Z, op.Flags,
                                old, oldExt, b.Block, b.ExtBlock);
                int index = lvl.PosToInt(b.X, b.Y, b.Z);
                BlockQueue.Addblock(p, index, b.Block, b.ExtBlock);
            }
            op.TotalModified++;
        }
        static void ConsoleOutputBlock(DrawOpBlock b, Level lvl, BufferedBlockSender buffer)
        {
            int index = lvl.PosToInt(b.X, b.Y, b.Z);

            if (!lvl.DoPhysicsBlockchange(index, b.Block, false,
                                          default(PhysicsArgs), b.ExtBlock))
            {
                return;
            }
            buffer.Add(index, b.Block, b.ExtBlock);
        }
Exemple #5
0
        public override void Perform(Vec3S32[] marks, Brush brush, DrawOpOutput output)
        {
            CopyState state = CopyState;
            bool      pasteAir = state.PasteAir;
            Vec3U16   p1 = Clamp(Min), p2 = Clamp(Max);

            for (ushort y = p1.Y; y <= p2.Y; y++)
            {
                for (ushort z = p1.Z; z <= p2.Z; z++)
                {
                    for (ushort x = p1.X; x <= p2.X; x++)
                    {
                        DrawOpBlock block = Place(x, y, z, brush);
                        if (pasteAir || block.Block.BlockID != Block.Air)
                        {
                            output(block);
                        }
                    }
                }
            }
        }
Exemple #6
0
        void OutputBlock(DrawOpBlock b, Action <DrawOpBlock> output)
        {
            int dx = b.X - P.X, dy = b.Y - P.Y, dz = b.Z - P.Z;

            // Scale out until we hit the next block
            for (int y = P.Y + dy * YMul / YDiv; y != P.Y + (dy + dirY) * YMul / YDiv; y += dirY)
            {
                for (int z = P.Z + dz * ZMul / ZDiv; z != P.Z + (dz + dirZ) * ZMul / ZDiv; z += dirZ)
                {
                    for (int x = P.X + dx * XMul / XDiv; x != P.X + (dx + dirX) * XMul / XDiv; x += dirX)
                    {
                        if (x < 0 || y < 0 || z < 0 || x >= width || y >= height || z >= length)
                        {
                            continue;
                        }
                        b.X = (ushort)x; b.Y = (ushort)y; b.Z = (ushort)z;
                        output(b);
                    }
                }
            }
        }
            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();
            }
Exemple #8
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();
            }