Ejemplo n.º 1
0
        public bool DoPhysicsBlockchange(int b, BlockID block, bool overRide = false,
                                         PhysicsArgs data = default(PhysicsArgs), bool addUndo = true)
        {
            if (blocks == null || b < 0 || b >= blocks.Length)
            {
                return(false);
            }
            BlockID old = blocks[b];

            #if TEN_BIT_BLOCKS
            BlockID extended = Block.ExtendedBase[old];
            if (extended > 0)
            {
                old = (BlockID)(extended | GetExtTile(b));
            }
            #else
            if (old == Block.custom_block)
            {
                old = (BlockID)(Block.Extended | GetExtTile(b));
            }
            #endif

            try
            {
                if (!overRide)
                {
                    if (Props[old].OPBlock || (Props[block].OPBlock && data.Raw != 0))
                    {
                        return(false);
                    }
                }

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

                if (addUndo)
                {
                    UndoPos uP = default(UndoPos);
                    uP.Index = b;
                    uP.SetData(old, block);

                    if (UndoBuffer.Count < Server.Config.PhysicsUndo)
                    {
                        UndoBuffer.Add(uP);
                    }
                    else
                    {
                        if (currentUndo >= Server.Config.PhysicsUndo)
                        {
                            currentUndo = 0;
                        }
                        UndoBuffer[currentUndo] = uP;
                    }
                    currentUndo++;
                }

                Changed = true;
                if (block >= Block.Extended)
                {
                    #if TEN_BIT_BLOCKS
                    blocks[b] = Block.ExtendedClass[block >> Block.ExtendedShift];
                    #else
                    blocks[b] = Block.custom_block;
                    #endif
                    ushort x, y, z;
                    IntToPos(b, out x, out y, out z);
                    FastSetExtTile(x, y, z, (BlockRaw)block);
                }
                else
                {
                    blocks[b] = (BlockRaw)block;
                    if (old >= Block.Extended)
                    {
                        ushort x, y, z;
                        IntToPos(b, out x, out y, out z);
                        FastRevertExtTile(x, y, z);
                    }
                }
                if (physics > 0 && (ActivatesPhysics(block) || data.Raw != 0))
                {
                    AddCheck(b, false, data);
                }

                // Save bandwidth not sending identical looking blocks, like air/op_air changes.
                return(!Block.VisuallyEquals(old, block));
            } catch {
                return(false);
            }
        }
Ejemplo n.º 2
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();
            }
Ejemplo n.º 3
0
        /// <summary> Retrieves the default physics block handler for the given block. </summary>
        internal static HandlePhysics GetPhysicsHandler(BlockID block, BlockProps[] props)
        {
            switch (block)
            {
            case Block.Door_Log_air:   return(DoorPhysics.Do);

            case Block.Door_TNT_air:   return(DoorPhysics.Do);

            case Block.Door_Green_air: return(DoorPhysics.Do);

            case Block.SnakeTail: return(SnakePhysics.DoTail);

            case Block.Snake: return(SnakePhysics.Do);

            case Block.RocketHead: return(RocketPhysics.Do);

            case Block.Fireworks: return(FireworkPhysics.Do);

            case Block.ZombieBody: return(ZombiePhysics.Do);

            case Block.ZombieHead: return(ZombiePhysics.DoHead);

            case Block.Creeper: return(ZombiePhysics.Do);

            case Block.Water: return(SimpleLiquidPhysics.DoWater);

            case Block.Deadly_ActiveWater: return(SimpleLiquidPhysics.DoWater);

            case Block.Lava: return(SimpleLiquidPhysics.DoLava);

            case Block.Deadly_ActiveLava: return(SimpleLiquidPhysics.DoLava);

            case Block.WaterDown: return(ExtLiquidPhysics.DoWaterfall);

            case Block.LavaDown: return(ExtLiquidPhysics.DoLavafall);

            case Block.WaterFaucet: return((Level lvl, ref PhysInfo C) =>
                                           ExtLiquidPhysics.DoFaucet(lvl, ref C, Block.WaterDown));

            case Block.LavaFaucet: return((Level lvl, ref PhysInfo C) =>
                                          ExtLiquidPhysics.DoFaucet(lvl, ref C, Block.LavaDown));

            case Block.FiniteWater: return(FinitePhysics.DoWaterOrLava);

            case Block.FiniteLava: return(FinitePhysics.DoWaterOrLava);

            case Block.FiniteFaucet: return(FinitePhysics.DoFaucet);

            case Block.Magma: return(ExtLiquidPhysics.DoMagma);

            case Block.Geyser: return(ExtLiquidPhysics.DoGeyser);

            case Block.FastLava: return(SimpleLiquidPhysics.DoFastLava);

            case Block.Deadly_FastLava: return(SimpleLiquidPhysics.DoFastLava);

            case Block.Air: return(AirPhysics.DoAir);

            case Block.Leaves: return(LeafPhysics.DoLeaf);

            case Block.Sapling: return(OtherPhysics.DoShrub);

            case Block.Fire: return(FirePhysics.Do);

            case Block.LavaFire: return(FirePhysics.Do);

            case Block.Sand: return(OtherPhysics.DoFalling);

            case Block.Gravel: return(OtherPhysics.DoFalling);

            case Block.FloatWood: return(OtherPhysics.DoFloatwood);

            case Block.Sponge: return((Level lvl, ref PhysInfo C) =>
                                      OtherPhysics.DoSponge(lvl, ref C, false));

            case Block.LavaSponge: return((Level lvl, ref PhysInfo C) =>
                                          OtherPhysics.DoSponge(lvl, ref C, true));

            // Special blocks that are not saved
            case Block.Air_Flood: return((Level lvl, ref PhysInfo C) =>
                                         AirPhysics.DoFlood(lvl, ref C, AirFlood.Full, Block.Air_Flood));

            case Block.Air_FloodLayer: return((Level lvl, ref PhysInfo C) =>
                                              AirPhysics.DoFlood(lvl, ref C, AirFlood.Layer, Block.Air_FloodLayer));

            case Block.Air_FloodDown: return((Level lvl, ref PhysInfo C) =>
                                             AirPhysics.DoFlood(lvl, ref C, AirFlood.Down, Block.Air_FloodDown));

            case Block.Air_FloodUp: return((Level lvl, ref PhysInfo C) =>
                                           AirPhysics.DoFlood(lvl, ref C, AirFlood.Up, Block.Air_FloodUp));

            case Block.TNT_Small: return(TntPhysics.DoSmallTnt);

            case Block.TNT_Big: return(TntPhysics.DoBigTnt);

            case Block.TNT_Nuke: return(TntPhysics.DoNukeTnt);

            case Block.TNT_Explosion: return(TntPhysics.DoTntExplosion);

            case Block.Train: return(TrainPhysics.Do);
            }

            HandlePhysics animalAI = AnimalAIHandler(props[block].AnimalAI);

            if (animalAI != null)
            {
                return(animalAI);
            }
            if (props[block].oDoorBlock != Block.Invalid)
            {
                return(DoorPhysics.oDoor);
            }
            if (props[block].GrassBlock != Block.Invalid)
            {
                return(OtherPhysics.DoDirtGrow);
            }
            if (props[block].DirtBlock != Block.Invalid)
            {
                return(OtherPhysics.DoGrassDie);
            }

            // TODO: should this be checking WaterKills/LavaKills
            // Adv physics updating anything placed next to water or lava
            if ((block >= Block.Red && block <= Block.RedMushroom) || block == Block.Wood || block == Block.Log || block == Block.Bookshelf)
            {
                return(OtherPhysics.DoOther);
            }
            return(null);
        }
Ejemplo n.º 4
0
        /// <summary> Performs a user like block change, but **DOES NOT** update the BlockDB. </summary>
        /// <remarks> The return code can be used to avoid sending redundant block changes. </remarks>
        /// <remarks> Does NOT send the changed block to any players - use BroadcastChange. </remarks>
        public ChangeResult TryChangeBlock(Player p, ushort x, ushort y, ushort z, BlockID block, bool drawn = false)
        {
            string errorLocation = "start";

            try
            {
                BlockID old = GetBlock(x, y, z);
                if (old == Block.Invalid)
                {
                    return(ChangeResult.Unchanged);
                }

                errorLocation = "Permission checking";
                if (!CheckAffect(p, x, y, z, old, block))
                {
                    return(ChangeResult.Unchanged);
                }
                if (old == block)
                {
                    return(ChangeResult.Unchanged);
                }

                if (old == Block.Sponge && physics > 0 && block != Block.Sponge)
                {
                    OtherPhysics.DoSpongeRemoved(this, PosToInt(x, y, z), false);
                }
                if (old == Block.LavaSponge && physics > 0 && block != Block.LavaSponge)
                {
                    OtherPhysics.DoSpongeRemoved(this, PosToInt(x, y, z), true);
                }

                p.TotalModified++;
                if (drawn)
                {
                    p.TotalDrawn++;
                }
                else if (block == Block.Air)
                {
                    p.TotalDeleted++;
                }
                else
                {
                    p.TotalPlaced++;
                }

                errorLocation = "Setting tile";
                if (block >= Block.Extended)
                {
                    #if TEN_BIT_BLOCKS
                    SetTile(x, y, z, Block.ExtendedClass[block >> Block.ExtendedShift]);
                    #else
                    SetTile(x, y, z, Block.custom_block);
                    #endif
                    FastSetExtTile(x, y, z, (BlockRaw)block);
                }
                else
                {
                    SetTile(x, y, z, (BlockRaw)block);
                    if (old >= Block.Extended)
                    {
                        FastRevertExtTile(x, y, z);
                    }
                }

                errorLocation = "Adding physics";
                if (physics > 0 && ActivatesPhysics(block))
                {
                    AddCheck(PosToInt(x, y, z));
                }

                Changed            = true;
                ChangedSinceBackup = true;

                return(Block.VisuallyEquals(old, block) ? ChangeResult.VisuallySame : ChangeResult.Modified);
            } catch (Exception e) {
                Logger.LogError(e);
                Chat.MessageOps(p.name + " triggered a non-fatal error on " + ColoredName + ", &Sat location: " + errorLocation);
                Logger.Log(LogType.Warning, "{0} triggered a non-fatal error on {1}, &Sat location: {2}",
                           p.name, ColoredName, errorLocation);
                return(0);
            }
        }
Ejemplo n.º 5
0
        internal static void SetupCorePhysicsHandlers()
        {
            physicsHandlers[Block.birdblack] = BirdPhysics.Do;
            physicsHandlers[Block.birdwhite] = BirdPhysics.Do;
            physicsHandlers[Block.birdlava]  = BirdPhysics.Do;
            physicsHandlers[Block.birdwater] = BirdPhysics.Do;
            physicsHandlers[Block.birdred]   = (Level lvl, ref Check C) => HunterPhysics.DoKiller(lvl, ref C, Block.air);
            physicsHandlers[Block.birdblue]  = (Level lvl, ref Check C) => HunterPhysics.DoKiller(lvl, ref C, Block.air);
            physicsHandlers[Block.birdkill]  = (Level lvl, ref Check C) => HunterPhysics.DoKiller(lvl, ref C, Block.air);

            physicsHandlers[Block.snaketail]  = SnakePhysics.DoTail;
            physicsHandlers[Block.snake]      = SnakePhysics.Do;
            physicsHandlers[Block.rockethead] = RocketPhysics.Do;
            physicsHandlers[Block.firework]   = FireworkPhysics.Do;
            physicsHandlers[Block.zombiebody] = ZombiePhysics.Do;
            physicsHandlers[Block.zombiehead] = ZombiePhysics.DoHead;
            physicsHandlers[Block.creeper]    = ZombiePhysics.Do;

            physicsHandlers[Block.fishbetta]     = (Level lvl, ref Check C) => HunterPhysics.DoKiller(lvl, ref C, Block.water);
            physicsHandlers[Block.fishshark]     = (Level lvl, ref Check C) => HunterPhysics.DoKiller(lvl, ref C, Block.water);
            physicsHandlers[Block.fishlavashark] = (Level lvl, ref Check C) => HunterPhysics.DoKiller(lvl, ref C, Block.lava);
            physicsHandlers[Block.fishgold]      = (Level lvl, ref Check C) => HunterPhysics.DoFlee(lvl, ref C, Block.water);
            physicsHandlers[Block.fishsalmon]    = (Level lvl, ref Check C) => HunterPhysics.DoFlee(lvl, ref C, Block.water);
            physicsHandlers[Block.fishsponge]    = (Level lvl, ref Check C) => HunterPhysics.DoFlee(lvl, ref C, Block.water);

            physicsHandlers[Block.water]            = SimpleLiquidPhysics.DoWater;
            physicsHandlers[Block.activedeathwater] = SimpleLiquidPhysics.DoWater;
            physicsHandlers[Block.lava]             = SimpleLiquidPhysics.DoLava;
            physicsHandlers[Block.activedeathlava]  = SimpleLiquidPhysics.DoLava;
            physicsHandlers[Block.WaterDown]        = ExtLiquidPhysics.DoWaterfall;
            physicsHandlers[Block.LavaDown]         = ExtLiquidPhysics.DoLavafall;
            physicsHandlers[Block.WaterFaucet]      = (Level lvl, ref Check C) =>
                                                      ExtLiquidPhysics.DoFaucet(lvl, ref C, Block.WaterDown);
            physicsHandlers[Block.LavaFaucet] = (Level lvl, ref Check C) =>
                                                ExtLiquidPhysics.DoFaucet(lvl, ref C, Block.LavaDown);
            physicsHandlers[Block.finiteWater]   = FinitePhysics.DoWaterOrLava;
            physicsHandlers[Block.finiteLava]    = FinitePhysics.DoWaterOrLava;
            physicsHandlers[Block.finiteFaucet]  = FinitePhysics.DoFaucet;
            physicsHandlers[Block.magma]         = ExtLiquidPhysics.DoMagma;
            physicsHandlers[Block.geyser]        = ExtLiquidPhysics.DoGeyser;
            physicsHandlers[Block.lava_fast]     = SimpleLiquidPhysics.DoFastLava;
            physicsHandlers[Block.fastdeathlava] = SimpleLiquidPhysics.DoFastLava;

            physicsHandlers[Block.air]             = AirPhysics.DoAir;
            physicsHandlers[Block.dirt]            = OtherPhysics.DoDirt;
            physicsHandlers[Block.leaf]            = LeafPhysics.DoLeaf;
            physicsHandlers[Block.shrub]           = OtherPhysics.DoShrub;
            physicsHandlers[Block.fire]            = FirePhysics.Do;
            physicsHandlers[Block.lava_fire]       = FirePhysics.Do;
            physicsHandlers[Block.sand]            = OtherPhysics.DoFalling;
            physicsHandlers[Block.gravel]          = OtherPhysics.DoFalling;
            physicsHandlers[Block.cobblestoneslab] = OtherPhysics.DoStairs;
            physicsHandlers[Block.staircasestep]   = OtherPhysics.DoStairs;
            physicsHandlers[Block.wood_float]      = OtherPhysics.DoFloatwood;

            physicsHandlers[Block.sponge]      = (Level lvl, ref Check C) => OtherPhysics.DoSponge(lvl, ref C, false);
            physicsHandlers[Block.lava_sponge] = (Level lvl, ref Check C) => OtherPhysics.DoSponge(lvl, ref C, true);

            //Special blocks that are not saved
            physicsHandlers[Block.air_flood] = (Level lvl, ref Check C) =>
                                               AirPhysics.DoFlood(lvl, ref C, AirFlood.Full, Block.air_flood);
            physicsHandlers[Block.air_flood_layer] = (Level lvl, ref Check C) =>
                                                     AirPhysics.DoFlood(lvl, ref C, AirFlood.Layer, Block.air_flood_layer);
            physicsHandlers[Block.air_flood_down] = (Level lvl, ref Check C) =>
                                                    AirPhysics.DoFlood(lvl, ref C, AirFlood.Down, Block.air_flood_down);
            physicsHandlers[Block.air_flood_up] = (Level lvl, ref Check C) =>
                                                  AirPhysics.DoFlood(lvl, ref C, AirFlood.Up, Block.air_flood_up);

            physicsHandlers[Block.smalltnt]     = TntPhysics.DoSmallTnt;
            physicsHandlers[Block.bigtnt]       = (Level lvl, ref Check C) => TntPhysics.DoLargeTnt(lvl, ref C, 1);
            physicsHandlers[Block.nuketnt]      = (Level lvl, ref Check C) => TntPhysics.DoLargeTnt(lvl, ref C, 4);
            physicsHandlers[Block.tntexplosion] = TntPhysics.DoTntExplosion;
            physicsHandlers[Block.train]        = TrainPhysics.Do;

            for (int i = 0; i < 256; i++)
            {
                //Adv physics updating anything placed next to water or lava
                if ((i >= Block.red && i <= Block.redmushroom) || i == Block.wood ||
                    i == Block.trunk || i == Block.bookcase)
                {
                    physicsHandlers[i] = OtherPhysics.DoOther;
                    continue;
                }

                if (Block.Props[i].ODoorId != Block.Invalid)
                {
                    physicsHandlers[i]      = DoorPhysics.oDoor;
                    physicsDoorsHandlers[i] = DoorPhysics.oDoor;
                }
            }
        }
Ejemplo n.º 6
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();
            }
Ejemplo n.º 7
0
        internal bool DoPhysicsBlockchange(int b, ExtBlock block, bool overRide = false,
                                           PhysicsArgs data = default(PhysicsArgs), bool addUndo = true)
        {
            if (blocks == null || b < 0 || b >= blocks.Length)
            {
                return(false);
            }
            ExtBlock old;

            old.BlockID = blocks[b];
            old.ExtID   = old.BlockID == Block.custom_block ? GetExtTile(b) : Block.Air;

            try
            {
                if (!overRide)
                {
                    if (Props[old.Index].OPBlock || (Props[block.Index].OPBlock && data.Raw != 0))
                    {
                        return(false);
                    }
                }

                if (old.BlockID == Block.Sponge && physics > 0 && block.BlockID != Block.Sponge)
                {
                    OtherPhysics.DoSpongeRemoved(this, b, false);
                }

                if (old.BlockID == Block.LavaSponge && physics > 0 && block.BlockID != Block.LavaSponge)
                {
                    OtherPhysics.DoSpongeRemoved(this, b, true);
                }

                if (addUndo)
                {
                    UndoPos uP = default(UndoPos);
                    uP.index = b;
                    uP.SetData(old, block);

                    if (UndoBuffer.Count < ServerConfig.PhysicsUndo)
                    {
                        UndoBuffer.Add(uP);
                    }
                    else
                    {
                        if (currentUndo >= ServerConfig.PhysicsUndo)
                        {
                            currentUndo = 0;
                        }
                        UndoBuffer[currentUndo] = uP;
                    }
                    currentUndo++;
                }

                blocks[b] = block.BlockID;
                Changed   = true;
                if (block.BlockID == Block.custom_block)
                {
                    ushort x, y, z;
                    IntToPos(b, out x, out y, out z);
                    SetExtTileNoCheck(x, y, z, block.ExtID);
                }
                else if (old.BlockID == Block.custom_block)
                {
                    ushort x, y, z;
                    IntToPos(b, out x, out y, out z);
                    RevertExtTileNoCheck(x, y, z);
                }
                if (physics > 0 && (ActivatesPhysics(block) || data.Raw != 0))
                {
                    AddCheck(b, false, data);
                }

                // Save bandwidth sending identical looking blocks, like air/op_air changes.
                return(!old.VisuallyEquals(block));
            } catch {
                blocks[b] = block.BlockID;
                return(false);
            }
        }
Ejemplo n.º 8
0
        /// <summary> Returns: <br/>
        /// 0 - block change was not performed <br/>
        /// 1 - old block was same as new block visually (e.g. white to door_white)<br/>
        /// 2 - old block was different to new block visually </summary>
        /// <remarks> The return code can be used to avoid sending redundant block changes. </remarks>
        public int DoBlockchange(Player p, ushort x, ushort y, ushort z, ExtBlock block, bool drawn = false)
        {
            string errorLocation = "start";

            try
            {
                if (x >= Width || y >= Height || z >= Length)
                {
                    return(0);
                }
                ExtBlock old = GetBlock(x, y, z);

                errorLocation = "Permission checking";
                if (!CheckAffectPermissions(p, x, y, z, old, block))
                {
                    p.RevertBlock(x, y, z); return(0);
                }
                if (old == block)
                {
                    return(0);
                }

                if (old.BlockID == Block.Sponge && physics > 0 && block.BlockID != Block.Sponge)
                {
                    OtherPhysics.DoSpongeRemoved(this, PosToInt(x, y, z), false);
                }
                if (old.BlockID == Block.LavaSponge && physics > 0 && block.BlockID != Block.LavaSponge)
                {
                    OtherPhysics.DoSpongeRemoved(this, PosToInt(x, y, z), true);
                }

                p.SessionModified++;
                p.TotalModified++;

                if (drawn)
                {
                    p.TotalDrawn++;
                }
                else if (block.BlockID == Block.Air)
                {
                    p.TotalDeleted++;
                }
                else
                {
                    p.TotalPlaced++;
                }

                errorLocation = "Setting tile";
                SetTile(x, y, z, block.BlockID);
                if (old.BlockID == Block.custom_block && block.BlockID != Block.custom_block)
                {
                    RevertExtTileNoCheck(x, y, z);
                }
                if (block.BlockID == Block.custom_block)
                {
                    SetExtTileNoCheck(x, y, z, block.ExtID);
                }

                errorLocation = "Adding physics";
                if (p.PlayingTntWars && block.BlockID == Block.TNT_Small)
                {
                    AddTntCheck(PosToInt(x, y, z), p);
                }
                if (physics > 0 && ActivatesPhysics(block))
                {
                    AddCheck(PosToInt(x, y, z));
                }

                Changed  = true;
                backedup = false;

                return(old.VisuallyEquals(block) ? 1 : 2);
            } catch (Exception e) {
                Logger.LogError(e);
                Chat.MessageOps(p.name + " triggered a non-fatal error on " + ColoredName + ", %Sat location: " + errorLocation);
                Logger.Log(LogType.Warning, "{0} triggered a non-fatal error on {1}, %Sat location: {2}",
                           p.name, ColoredName, errorLocation);
                return(0);
            }
        }
Ejemplo n.º 9
0
        internal bool DoPhysicsBlockchange(int b, byte block, bool overRide = false,
                                           PhysicsArgs data = default(PhysicsArgs),
                                           byte extBlock    = 0, bool addUndo = true)
        {
            if (b < 0 || b >= blocks.Length || blocks == null)
            {
                return(false);
            }
            byte old    = blocks[b];
            byte oldExt = old == Block.custom_block ? GetExtTile(b) : (byte)0;

            try
            {
                if (!overRide)
                {
                    if (Block.Props[old].OPBlock || (Block.Props[block].OPBlock && data.Raw != 0))
                    {
                        return(false);
                    }
                }

                if (b == Block.sponge && physics > 0 && block != Block.sponge)
                {
                    OtherPhysics.DoSpongeRemoved(this, b);
                }

                if (b == Block.lava_sponge && physics > 0 && block != Block.lava_sponge)
                {
                    OtherPhysics.DoSpongeRemoved(this, b, true);
                }

                if (addUndo)
                {
                    UndoPos uP = default(UndoPos);
                    uP.index = b;
                    uP.SetData(old, oldExt, block, extBlock);

                    if (UndoBuffer.Count < Server.physUndo)
                    {
                        UndoBuffer.Add(uP);
                    }
                    else
                    {
                        if (currentUndo >= Server.physUndo)
                        {
                            currentUndo = 0;
                        }
                        UndoBuffer[currentUndo] = uP;
                    }
                    currentUndo++;
                }

                blocks[b] = block;
                changed   = true;
                if (block == Block.custom_block)
                {
                    ushort x, y, z;
                    IntToPos(b, out x, out y, out z);
                    SetExtTileNoCheck(x, y, z, extBlock);
                }
                else if (old == Block.custom_block)
                {
                    ushort x, y, z;
                    IntToPos(b, out x, out y, out z);
                    RevertExtTileNoCheck(x, y, z);
                }
                if (physics > 0 && (ActivatesPhysics(block, extBlock) || data.Raw != 0))
                {
                    AddCheck(b, false, data);
                }

                // Save bandwidth sending identical looking blocks, like air/op_air changes.
                bool diffBlock = Block.Convert(old) != Block.Convert(block);
                if (!diffBlock && old == Block.custom_block)
                {
                    diffBlock = oldExt != extBlock;
                }
                return(diffBlock);
            } catch {
                blocks[b] = block;
                return(false);
            }
        }
Ejemplo n.º 10
0
        public bool DoBlockchange(Player p, ushort x, ushort y, ushort z,
                                  byte block, byte extBlock = 0, bool drawn = false)
        {
            string errorLocation = "start";

retry:
            try
            {
                //if (x < 0 || y < 0 || z < 0) return;
                if (x >= Width || y >= Height || z >= Length)
                {
                    return(false);
                }
                byte old = GetTile(x, y, z), extOld = 0;
                if (old == Block.custom_block)
                {
                    extOld = GetExtTile(x, y, z);
                }

                errorLocation = "Permission checking";
                if (!CheckAffectPermissions(p, x, y, z, old, block, extBlock))
                {
                    p.RevertBlock(x, y, z); return(false);
                }

                if (old == Block.sponge && physics > 0 && block != Block.sponge)
                {
                    OtherPhysics.DoSpongeRemoved(this, PosToInt(x, y, z));
                }
                if (old == Block.lava_sponge && physics > 0 && block != Block.lava_sponge)
                {
                    OtherPhysics.DoSpongeRemoved(this, PosToInt(x, y, z), true);
                }

                errorLocation = "Undo buffer filling";
                Player.UndoPos Pos;
                Pos.x         = x; Pos.y = y; Pos.z = z;
                Pos.mapName   = name;
                Pos.type      = old; Pos.extType = extOld;
                Pos.newtype   = block; Pos.newExtType = extBlock;
                Pos.timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds;
                p.UndoBuffer.Add(this, Pos);

                errorLocation = "Setting tile";
                p.IncrementBlockStats(block, drawn);

                SetTile(x, y, z, block);
                if (old == Block.custom_block && block != Block.custom_block)
                {
                    RevertExtTileNoCheck(x, y, z);
                }
                if (block == Block.custom_block)
                {
                    SetExtTileNoCheck(x, y, z, extBlock);
                }

                errorLocation = "Adding physics";
                if (p.PlayingTntWars && block == Block.smalltnt)
                {
                    AddTntCheck(PosToInt(x, y, z), p);
                }
                if (physics > 0 && ActivatesPhysics(block, extBlock))
                {
                    AddCheck(PosToInt(x, y, z));
                }

                changed  = true;
                backedup = false;
                bool diffBlock = old == Block.custom_block ? extOld != extBlock :
                                 Block.Convert(old) != Block.Convert(block);
                return(diffBlock);
            } catch (OutOfMemoryException) {
                Player.Message(p, "Undo buffer too big! Cleared!");
                p.UndoBuffer.Clear();
                p.RemoveInvalidUndos();
                goto retry;
            } catch (Exception e) {
                Server.ErrorLog(e);
                Chat.MessageOps(p.name + " triggered a non-fatal error on " + ColoredName);
                Chat.MessageOps("Error location: " + errorLocation);
                Server.s.Log(p.name + " triggered a non-fatal error on " + ColoredName);
                Server.s.Log("Error location: " + errorLocation);
                return(false);
            }
        }
Ejemplo n.º 11
0
        internal bool DoBlockchange(Player p, ushort x, ushort y, ushort z, byte type, byte extType = 0)
        {
            string errorLocation = "start";

retry:
            try
            {
                //if (x < 0 || y < 0 || z < 0) return;
                if (x >= Width || y >= Height || z >= Length)
                {
                    return(false);
                }
                byte b = GetTile(x, y, z), extB = 0;
                if (b == Block.custom_block)
                {
                    extB = GetExtTile(x, y, z);
                }

                errorLocation = "Permission checking";
                if (!CheckAffectPermissions(p, x, y, z, b, type, extType))
                {
                    p.RevertBlock(x, y, z); return(false);
                }

                if (b == Block.sponge && physics > 0 && type != Block.sponge)
                {
                    OtherPhysics.DoSpongeRemoved(this, PosToInt(x, y, z));
                }
                if (b == Block.lava_sponge && physics > 0 && type != Block.lava_sponge)
                {
                    OtherPhysics.DoSpongeRemoved(this, PosToInt(x, y, z), true);
                }

                errorLocation = "Undo buffer filling";
                Player.UndoPos Pos;
                Pos.x         = x; Pos.y = y; Pos.z = z;
                Pos.mapName   = name;
                Pos.type      = b; Pos.extType = extB;
                Pos.newtype   = type; Pos.newExtType = extType;
                Pos.timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds;
                p.UndoBuffer.Add(this, Pos);

                errorLocation = "Setting tile";
                p.loginBlocks++;
                p.overallBlocks++;
                SetTile(x, y, z, type);
                if (b == Block.custom_block && type != Block.custom_block)
                {
                    RevertExtTileNoCheck(x, y, z);
                }
                if (type == Block.custom_block)
                {
                    SetExtTileNoCheck(x, y, z, extType);
                }

                errorLocation = "Adding physics";
                if (p.PlayingTntWars && type == Block.smalltnt)
                {
                    AddTntCheck(PosToInt(x, y, z), p);
                }
                if (physics > 0 && Block.Physics(type))
                {
                    AddCheck(PosToInt(x, y, z));
                }

                changed  = true;
                backedup = false;
                bool diffBlock = b == Block.custom_block ? extB != extType :
                                 Block.Convert(b) != Block.Convert(type);
                return(diffBlock);
            } catch (OutOfMemoryException) {
                Player.SendMessage(p, "Undo buffer too big! Cleared!");
                p.UndoBuffer.Clear();
                p.RemoveInvalidUndos();
                goto retry;
            } catch (Exception e) {
                Server.ErrorLog(e);
                Chat.GlobalMessageOps(p.name + " triggered a non-fatal error on " + name);
                Chat.GlobalMessageOps("Error location: " + errorLocation);
                Server.s.Log(p.name + " triggered a non-fatal error on " + name);
                Server.s.Log("Error location: " + errorLocation);
                return(false);
            }
        }