internal static void CheckAt(Level lvl, ushort x, ushort y, ushort z)
        {
            int     index;
            BlockID block = lvl.GetBlock(x, y, z, out index);

            switch (block)
            {
            //case Block.water:
            //case Block.lava:
            case Block.Sapling:
            case Block.Sand:
            case Block.Gravel:
            case Block.Leaves:
            case Block.FloatWood:
                /*case Block.lava_fast:
                 * case Block.WaterDown:
                 * case Block.LavaDown:
                 * case Block.deathlava:
                 * case Block.deathwater:
                 * case Block.geyser:
                 * case Block.magma:*/
                lvl.AddCheck(index);
                break;

            default:
                block = Block.Convert(block);
                if (block == Block.Water || block == Block.Lava || (block >= Block.Red && block <= Block.White))
                {
                    lvl.AddCheck(index);
                }
                break;
            }
        }
示例#2
0
        static void Explode(Level lvl, ushort x, ushort y, ushort z,
                            int size, Random rand, int prob, TWGame game)
        {
            for (int xx = (x - size); xx <= (x + size); ++xx)
            {
                for (int yy = (y - size); yy <= (y + size); ++yy)
                {
                    for (int zz = (z - size); zz <= (z + size); ++zz)
                    {
                        int     index;
                        BlockID b = lvl.GetBlock((ushort)xx, (ushort)yy, (ushort)zz, out index);
                        if (b == Block.Invalid)
                        {
                            continue;
                        }

                        bool doDestroy = prob < 0 || rand.Next(1, 10) < prob;
                        if (doDestroy && Block.Convert(b) != Block.TNT)
                        {
                            if (game != null && b != Block.Air && !IsFuse(b, xx - x, yy - y, zz - z))
                            {
                                if (game.InZone((ushort)xx, (ushort)yy, (ushort)zz, game.tntImmuneZones))
                                {
                                    continue;
                                }
                            }

                            int mode = rand.Next(1, 11);
                            if (mode <= 4)
                            {
                                lvl.AddUpdate(index, Block.TNT_Explosion, default(PhysicsArgs));
                            }
                            else if (mode <= 8)
                            {
                                lvl.AddUpdate(index, Block.Air, default(PhysicsArgs));
                            }
                            else
                            {
                                PhysicsArgs args = default(PhysicsArgs);
                                args.Type1 = PhysicsArgs.Drop;      args.Value1 = 50;
                                args.Type2 = PhysicsArgs.Dissipate; args.Value2 = 8;
                                lvl.AddCheck(index, false, args);
                            }
                        }
                        else if (b == Block.TNT)
                        {
                            lvl.AddUpdate(index, Block.TNT_Small, default(PhysicsArgs));
                        }
                        else if (b == Block.TNT_Small || b == Block.TNT_Big || b == Block.TNT_Nuke)
                        {
                            lvl.AddCheck(index);
                        }
                    }
                }
            }
        }
示例#3
0
        static void Explode(Level lvl, ushort x, ushort y, ushort z,
                            int size, Random rand, int prob, TntWarsGame game)
        {
            for (int xx = (x - size); xx <= (x + size); ++xx)
            {
                for (int yy = (y - size); yy <= (y + size); ++yy)
                {
                    for (int zz = (z - size); zz <= (z + size); ++zz)
                    {
                        int index = lvl.PosToInt((ushort)xx, (ushort)yy, (ushort)zz);
                        if (index < 0)
                        {
                            continue;
                        }
                        byte b = lvl.blocks[index];

                        bool doDestroy = prob < 0 || rand.Next(1, 10) < prob;
                        if (doDestroy && Block.Convert(b) != Block.tnt)
                        {
                            if (game != null && b != Block.air)
                            {
                                if (game.InZone((ushort)xx, (ushort)yy, (ushort)zz, false))
                                {
                                    continue;
                                }
                            }

                            int mode = rand.Next(1, 11);
                            if (mode <= 4)
                            {
                                lvl.AddUpdate(index, Block.tntexplosion);
                            }
                            else if (mode <= 8)
                            {
                                lvl.AddUpdate(index, Block.air);
                            }
                            else
                            {
                                PhysicsArgs args = default(PhysicsArgs);
                                args.Type1 = PhysicsArgs.Drop; args.Value1 = 50;
                                args.Type2 = PhysicsArgs.Dissipate; args.Value2 = 8;
                                lvl.AddCheck(index, false, args);
                            }
                        }
                        else if (b == Block.tnt)
                        {
                            lvl.AddUpdate(index, Block.smalltnt);
                        }
                        else if (b == Block.smalltnt || b == Block.bigtnt || b == Block.nuketnt)
                        {
                            lvl.AddCheck(index);
                        }
                    }
                }
            }
        }
示例#4
0
        public static void PhysLava(Level lvl, ushort x, ushort y, ushort z, BlockID type)
        {
            int     index;
            BlockID block = lvl.GetBlock(x, y, z, out index);

            if (LSGame.Instance.Running && LSGame.Instance.Map == lvl && LSGame.Instance.InSafeZone(x, y, z))
            {
                return;
            }

            switch (block)
            {
            case Block.Air:
                if (!lvl.CheckSpongeLava(x, y, z))
                {
                    lvl.AddUpdate(index, type);
                }
                break;

            case Block.Water:
            case Block.Deadly_ActiveWater:
                if (!lvl.CheckSpongeLava(x, y, z))
                {
                    lvl.AddUpdate(index, Block.Stone, default(PhysicsArgs));
                }
                break;

            case Block.Sand:
                if (lvl.physics > 1)       //Adv physics changes sand to glass next to lava
                {
                    lvl.AddUpdate(index, Block.Glass, default(PhysicsArgs));
                }
                else
                {
                    lvl.AddCheck(index);
                } break;

            case Block.Gravel:
                lvl.AddCheck(index); break;

            default:
                //Adv physics kills flowers, wool, mushrooms, and wood type blocks in lava
                if (!lvl.Props[block].LavaKills)
                {
                    break;
                }

                if (lvl.physics > 1 && !lvl.CheckSpongeLava(x, y, z))
                {
                    lvl.AddUpdate(index, Block.Air, default(PhysicsArgs));
                }
                break;
            }
        }
示例#5
0
        public static void DoSpongeRemoved(Level lvl, int b, bool lava)
        {
            BlockID target = lava ? Block.Lava : Block.Water;
            BlockID alt = lava ? Block.StillLava : Block.StillWater;
            ushort  x, y, z;

            lvl.IntToPos(b, out x, out y, out z);

            for (int yy = -3; yy <= +3; ++yy)
            {
                for (int zz = -3; zz <= +3; ++zz)
                {
                    for (int xx = -3; xx <= +3; ++xx)
                    {
                        if (Math.Abs(xx) == 3 || Math.Abs(yy) == 3 || Math.Abs(zz) == 3) // Calc only edge
                        {
                            int     index;
                            BlockID block = lvl.GetBlock((ushort)(x + xx), (ushort)(y + yy), (ushort)(z + zz), out index);
                            if (Block.Convert(block) == target || Block.Convert(block) == alt)
                            {
                                lvl.AddCheck(index);
                            }
                        }
                    }
                }
            }
        }
示例#6
0
        static void CheckAround(Level lvl, ushort x, ushort y, ushort z, int newind)
        {
            int index, dx, dy, dz;

            for (dx = -2; dx < 3; dx++)
            {
                for (dy = -2; dy < 3; dy++)
                {
                    for (dz = -2; dz < 3; dz++)
                    {
                        if (dx == 0 && dy == 0 && dz == 0)
                        {
                            continue;
                        }

                        BlockID block = lvl.GetBlock((ushort)(x + dx), (ushort)(y + dy), (ushort)(z + dz), out index);
                        if (index == newind)
                        {
                            continue;
                        }

                        if (block == Block.FiniteWater || block == Block.FiniteLava)
                        {
                            lvl.AddCheck(index);
                        }
                    }
                }
            }
        }
示例#7
0
        public static void DoSpongeRemoved(Level lvl, int b, bool lava = false)
        {
            for (int y = -3; y <= +3; ++y)
            {
                for (int z = -3; z <= +3; ++z)
                {
                    for (int x = -3; x <= +3; ++x)
                    {
                        if (Math.Abs(x) == 3 || Math.Abs(y) == 3 || Math.Abs(z) == 3) //Calc only edge
                        {
                            int  index = lvl.IntOffset(b, x, y, z);
                            byte block = lvl.GetTile(index);
                            if (block == Block.Zero)
                            {
                                continue;
                            }

                            if ((!lava && Block.Convert(block) == Block.water) || (lava && Block.Convert(block) == Block.lava))
                            {
                                lvl.AddCheck(index);
                            }
                        }
                    }
                }
            }
        }
示例#8
0
        public static void DoSpongeRemoved(Level lvl, int b, bool lava)
        {
            byte target = lava ? Block.Lava : Block.Water;
            byte alt    = lava ? Block.StillLava : Block.StillWater;

            for (int y = -3; y <= +3; ++y)
            {
                for (int z = -3; z <= +3; ++z)
                {
                    for (int x = -3; x <= +3; ++x)
                    {
                        if (Math.Abs(x) == 3 || Math.Abs(y) == 3 || Math.Abs(z) == 3) //Calc only edge
                        {
                            int  index = lvl.IntOffset(b, x, y, z);
                            byte block = lvl.GetTile(index);
                            if (block == Block.Invalid)
                            {
                                continue;
                            }

                            if (Block.Convert(block) == target || Block.Convert(block) == alt)
                            {
                                lvl.AddCheck(index);
                            }
                        }
                    }
                }
            }
        }
示例#9
0
        static void CheckFallingBlocks(Level lvl, int b)
        {
            switch (lvl.blocks[b])
            {
            case Block.sand:
            case Block.gravel:
            case Block.wood_float:
                lvl.AddCheck(b); break;

            default:
                break;
            }
        }
示例#10
0
        static void CheckFallingBlocks(Level lvl, int b)
        {
            switch (lvl.blocks[b])
            {
            case Block.Sand:
            case Block.Gravel:
            case Block.FloatWood:
                lvl.AddCheck(b); break;

            default:
                break;
            }
        }
示例#11
0
        public static void PhysWater(Level lvl, ushort x, ushort y, ushort z, byte type)
        {
            int      b;
            ExtBlock block = lvl.GetBlock(x, y, z, out b);

            if (b == -1)
            {
                return;
            }
            if (Server.lava.active && Server.lava.map == lvl && Server.lava.InSafeZone(x, y, z))
            {
                return;
            }

            switch (block.BlockID)
            {
            case Block.Air:
                if (!lvl.CheckSpongeWater(x, y, z))
                {
                    lvl.AddUpdate(b, type);
                }
                break;

            case Block.Lava:
            case Block.FastLava:
            case Block.Deadly_ActiveLava:
                if (!lvl.CheckSpongeWater(x, y, z))
                {
                    lvl.AddUpdate(b, Block.Stone);
                }
                break;

            case Block.Sand:
            case Block.Gravel:
            case Block.FloatWood:
                lvl.AddCheck(b); break;

            default:
                // Adv physics kills flowers and mushrooms in water
                if (!lvl.Props[block.Index].WaterKills)
                {
                    break;
                }

                if (lvl.physics > 1 && !lvl.CheckSpongeWater(x, y, z))
                {
                    lvl.AddUpdate(b, Block.Air);
                }
                break;
            }
        }
示例#12
0
        public static void PhysWater(Level lvl, ushort x, ushort y, ushort z, byte type)
        {
            if (x >= lvl.Width || y >= lvl.Height || z >= lvl.Length)
            {
                return;
            }
            if (Server.lava.active && Server.lava.map == lvl && Server.lava.InSafeZone(x, y, z))
            {
                return;
            }

            int b = x + (z * lvl.Width) + (y * lvl.Width * lvl.Length);

            switch (lvl.blocks[b])
            {
            case Block.air:
                if (!lvl.CheckSpongeWater(x, y, z))
                {
                    lvl.AddUpdate(b, type);
                }
                break;

            case Block.lava:
            case Block.lava_fast:
            case Block.activedeathlava:
                if (!lvl.CheckSpongeWater(x, y, z))
                {
                    lvl.AddUpdate(b, Block.rock);
                }
                break;

            case Block.shrub:
            case Block.yellowflower:
            case Block.redflower:
            case Block.mushroom:
            case Block.redmushroom:
                if (lvl.physics > 1 && lvl.physics != 5 && !lvl.CheckSpongeWater(x, y, z))
                {
                    lvl.AddUpdate(b, Block.air);     //Adv physics kills flowers and mushrooms in water
                }
                break;

            case Block.sand:
            case Block.gravel:
            case Block.wood_float:
                lvl.AddCheck(b); break;

            default:
                break;
            }
        }
示例#13
0
        internal static void CheckAt(Level lvl, int index)
        {
            if (index == -1)
            {
                return;
            }
            byte block     = lvl.blocks[index];
            byte convBlock = Block.Convert(block);

            if (convBlock == Block.Water || convBlock == Block.Lava ||
                (block >= Block.Red && block <= Block.White))
            {
                lvl.AddCheck(index); return;
            }

            switch (block)
            {
            //case Block.water:
            //case Block.lava:
            case Block.Sapling:
            case Block.Sand:
            case Block.Gravel:
            case Block.Leaves:
            case Block.FloatWood:
                /*case Block.lava_fast:
                 * case Block.WaterDown:
                 * case Block.LavaDown:
                 * case Block.deathlava:
                 * case Block.deathwater:
                 * case Block.geyser:
                 * case Block.magma:*/
                lvl.AddCheck(index);
                break;

            default:
                break;
            }
        }
示例#14
0
        internal static void PhysAir(Level lvl, int index)
        {
            if (index == -1)
            {
                return;
            }
            byte block     = lvl.blocks[index];
            byte convBlock = Block.Convert(block);

            if (convBlock == Block.water || convBlock == Block.lava ||
                (block >= Block.red && block <= Block.white))
            {
                lvl.AddCheck(index); return;
            }

            switch (block)
            {
            //case Block.water:
            //case Block.lava:
            case Block.shrub:
            case Block.sand:
            case Block.gravel:
            case Block.leaf:
            case Block.wood_float:
                /*case Block.lava_fast:
                 * case Block.WaterDown:
                 * case Block.LavaDown:
                 * case Block.deathlava:
                 * case Block.deathwater:
                 * case Block.geyser:
                 * case Block.magma:*/
                lvl.AddCheck(index);
                break;

            default:
                break;
            }
        }
示例#15
0
        public static void PhysWater(Level lvl, ushort x, ushort y, ushort z, BlockID type)
        {
            int     index;
            BlockID block = lvl.GetBlock(x, y, z, out index);

            if (LSGame.Instance.Running && LSGame.Instance.Map == lvl && LSGame.Instance.InSafeZone(x, y, z))
            {
                return;
            }

            switch (block)
            {
            case Block.Air:
                if (!lvl.CheckSpongeWater(x, y, z))
                {
                    lvl.AddUpdate(index, type);
                }
                break;

            case Block.Lava:
            case Block.FastLava:
            case Block.Deadly_ActiveLava:
                if (!lvl.CheckSpongeWater(x, y, z))
                {
                    lvl.AddUpdate(index, Block.Stone, default(PhysicsArgs));
                }
                break;

            case Block.Sand:
            case Block.Gravel:
            case Block.FloatWood:
                lvl.AddCheck(index); break;

            default:
                // Adv physics kills flowers and mushrooms in water
                if (!lvl.Props[block].WaterKills)
                {
                    break;
                }

                if (lvl.physics > 1 && !lvl.CheckSpongeWater(x, y, z))
                {
                    lvl.AddUpdate(index, Block.Air, default(PhysicsArgs));
                }
                break;
            }
        }
示例#16
0
        public static void DoLog(Level lvl, ref PhysInfo C)
        {
            ushort x = C.X, y = C.Y, z = C.Z;

            for (int xx = -range; xx <= range; xx++)
            {
                for (int yy = -range; yy <= range; yy++)
                {
                    for (int zz = -range; zz <= range; zz++)
                    {
                        int index = lvl.PosToInt((ushort)(x + xx), (ushort)(y + yy), (ushort)(z + zz));
                        if (index < 0 || lvl.blocks[index] != Block.Leaves)
                        {
                            continue;
                        }

                        lvl.AddCheck(index);
                    }
                }
            }
            C.Data.Data = PhysicsArgs.RemoveFromChecks;
        }
示例#17
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();
            }
示例#18
0
        public static void PhysLava(Level lvl, ushort x, ushort y, ushort z, byte type)
        {
            int b = lvl.PosToInt(x, y, z);

            if (b == -1)
            {
                return;
            }
            if (Server.lava.active && Server.lava.map == lvl && Server.lava.InSafeZone(x, y, z))
            {
                return;
            }

            switch (lvl.blocks[b])
            {
            case Block.air:
                if (!lvl.CheckSpongeLava(x, y, z))
                {
                    lvl.AddUpdate(b, type);
                }
                break;

            case Block.water:
            case Block.activedeathwater:
                if (!lvl.CheckSpongeLava(x, y, z))
                {
                    lvl.AddUpdate(b, Block.rock);
                }
                break;

            case Block.sand:
                if (lvl.physics > 1)       //Adv physics changes sand to glass next to lava
                {
                    if (lvl.physics != 5)
                    {
                        lvl.AddUpdate(b, Block.glass);
                    }
                }
                else
                {
                    lvl.AddCheck(b);
                } break;

            case Block.gravel:
                lvl.AddCheck(b); break;

            default:
                //Adv physics kills flowers, wool, mushrooms, and wood type blocks in lava
                byte block = lvl.blocks[b];
                if (block != Block.custom_block)
                {
                    if (!Block.Props[block].LavaKills)
                    {
                        break;
                    }
                }
                else
                {
                    block = lvl.GetExtTile(b);
                    if (!lvl.CustomBlockProps[block].LavaKills)
                    {
                        break;
                    }
                }

                if (lvl.physics > 1 && !lvl.CheckSpongeLava(x, y, z))
                {
                    lvl.AddUpdate(b, Block.air);
                }
                break;
            }
        }
示例#19
0
        public static void PhysLava(Level lvl, ushort x, ushort y, ushort z, byte type)
        {
            int      b;
            ExtBlock block = lvl.GetBlock(x, y, z, out b);

            if (b == -1)
            {
                return;
            }
            if (Server.lava.active && Server.lava.map == lvl && Server.lava.InSafeZone(x, y, z))
            {
                return;
            }

            switch (block.BlockID)
            {
            case Block.Air:
                if (!lvl.CheckSpongeLava(x, y, z))
                {
                    lvl.AddUpdate(b, type);
                }
                break;

            case Block.Water:
            case Block.Deadly_ActiveWater:
                if (!lvl.CheckSpongeLava(x, y, z))
                {
                    lvl.AddUpdate(b, Block.Stone);
                }
                break;

            case Block.Sand:
                if (lvl.physics > 1)       //Adv physics changes sand to glass next to lava
                {
                    if (lvl.physics != 5)
                    {
                        lvl.AddUpdate(b, Block.Glass);
                    }
                }
                else
                {
                    lvl.AddCheck(b);
                } break;

            case Block.Gravel:
                lvl.AddCheck(b); break;

            default:
                //Adv physics kills flowers, wool, mushrooms, and wood type blocks in lava
                if (!lvl.Props[block.Index].LavaKills)
                {
                    break;
                }

                if (lvl.physics > 1 && !lvl.CheckSpongeLava(x, y, z))
                {
                    lvl.AddUpdate(b, Block.Air);
                }
                break;
            }
        }
示例#20
0
        internal static void PhysAir(Level lvl, int b) {
            if (b == -1)
                return;
            byte block = lvl.blocks[b];
            byte convBlock = Block.Convert(block);
            if (convBlock == Block.water || convBlock == Block.lava ||
                (block >= Block.red && block <= Block.white)) {
                lvl.AddCheck(b); return;
            }

            switch (block) {
                    //case Block.water:
                    //case Block.lava:
                case Block.shrub:
                case Block.sand:
                case Block.gravel:
                case Block.leaf:
                case Block.wood_float:
                    /*case Block.lava_fast:
                    case Block.WaterDown:
                    case Block.LavaDown:
                    case Block.deathlava:
                    case Block.deathwater:
                    case Block.geyser:
                    case Block.magma:*/
                    lvl.AddCheck(b);
                    break;
                default:
                    break;
            }
        }
示例#21
0
        public static void PhysWater(Level lvl, ushort x, ushort y, ushort z, byte type)
        {
            int b = lvl.PosToInt(x, y, z);

            if (b == -1)
            {
                return;
            }
            if (Server.lava.active && Server.lava.map == lvl && Server.lava.InSafeZone(x, y, z))
            {
                return;
            }

            switch (lvl.blocks[b])
            {
            case Block.air:
                if (!lvl.CheckSpongeWater(x, y, z))
                {
                    lvl.AddUpdate(b, type);
                }
                break;

            case Block.lava:
            case Block.lava_fast:
            case Block.activedeathlava:
                if (!lvl.CheckSpongeWater(x, y, z))
                {
                    lvl.AddUpdate(b, Block.rock);
                }
                break;

            case Block.sand:
            case Block.gravel:
            case Block.wood_float:
                lvl.AddCheck(b); break;

            default:
                // //Adv physics kills flowers and mushrooms in water
                byte block = lvl.blocks[b];
                if (block != Block.custom_block)
                {
                    if (!Block.Props[block].WaterKills)
                    {
                        break;
                    }
                }
                else
                {
                    block = lvl.GetExtTile(b);
                    if (!lvl.CustomBlockProps[block].WaterKills)
                    {
                        break;
                    }
                }

                if (lvl.physics > 1 && !lvl.CheckSpongeWater(x, y, z))
                {
                    lvl.AddUpdate(b, Block.air);
                }
                break;
            }
        }
示例#22
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();
            }
示例#23
0
        public static void PhysLava(Level lvl, ushort x, ushort y, ushort z, byte type)
        {
            if (x >= lvl.Width || y >= lvl.Height || z >= lvl.Length)
            {
                return;
            }
            if (Server.lava.active && Server.lava.map == lvl && Server.lava.InSafeZone(x, y, z))
            {
                return;
            }

            int b = x + lvl.Width * (z + y * lvl.Length);

            if (lvl.physics > 1 && lvl.physics != 5 && !lvl.CheckSpongeLava(x, y, z) && lvl.blocks[b] >= 21 && lvl.blocks[b] <= 36)
            {
                lvl.AddUpdate(b, Block.air); return;
            } // Adv physics destroys cloth

            switch (lvl.blocks[b])
            {
            case Block.air:
                if (!lvl.CheckSpongeLava(x, y, z))
                {
                    lvl.AddUpdate(b, type);
                }
                break;

            case Block.water:
            case Block.activedeathwater:
                if (!lvl.CheckSpongeLava(x, y, z))
                {
                    lvl.AddUpdate(b, Block.rock);
                }
                break;

            case Block.sand:
                if (lvl.physics > 1)       //Adv physics changes sand to glass next to lava
                {
                    if (lvl.physics != 5)
                    {
                        lvl.AddUpdate(b, Block.glass);
                    }
                }
                else
                {
                    lvl.AddCheck(b);
                } break;

            case Block.gravel:
                lvl.AddCheck(b); break;

            case Block.wood:
            case Block.shrub:
            case Block.trunk:
            case Block.leaf:
            case Block.yellowflower:
            case Block.redflower:
            case Block.mushroom:
            case Block.redmushroom:
                if (lvl.physics > 1 && lvl.physics != 5)     //Adv physics kills flowers and mushrooms plus wood in lava
                {
                    if (!lvl.CheckSpongeLava(x, y, z))
                    {
                        lvl.AddUpdate(b, Block.air);
                    }
                }
                break;
            }
        }