Structure representing a pending update to the map's block array. Contains information about the block coordinates, type, and change's origin.
Example #1
0
        public void ClearUpdateQueue()
        {
            BlockUpdate temp = new BlockUpdate();

            while (updates.Dequeue(ref temp))
            {
            }
        }
Example #2
0
        public bool FireChangedBlockEvent(ref BlockUpdate update)
        {
            bool cancel = false;

            if (OnPlayerChangedBlock != null)
            {
                OnPlayerChangedBlock(this, ref update, ref cancel);
            }
            return(!cancel);
        }
Example #3
0
        /// <summary>
        /// Updates a specific block for a given time
        /// </summary>
        private void updateBlock(Block blockType, Vector3I blockPosition, bool replaceWithAir, double time)        //I left this class rather generic incase i used it for anything else
        {
            BlockUpdate update = new BlockUpdate(null, blockPosition, blockType);

            foreach (Player p in World.Players)
            {
                p.World.Map.QueueUpdate(update);
            }

            if (replaceWithAir)
            {
                Scheduler.NewTask(t => updateBlock(Block.Air, blockPosition, false, time)).RunManual(TimeSpan.FromSeconds(time));                //place a block, replace it with air once 'time' is up
            }
        }
Example #4
0
        public static void RemoveSolid(Player p)
        {
            if (p.IsSolidBlock && !p.IsPropHuntTagged)
            {
                //Remove the players block
                Block       airBlock    = Block.Air;
                BlockUpdate blockUpdate = new BlockUpdate(null, p.prophuntSolidPos, airBlock);
                p.World.Map.QueueUpdate(blockUpdate);

                //Do the other stuff
                p.Message("You are no longer a solid block!");
                p.IsSolidBlock  = false;
                p.Info.IsHidden = false;
                Player.RaisePlayerHideChangedEvent(p);
            }
        }
Example #5
0
        // checks for idle players
        public static void CheckIdles(SchedulerTask task)
        {
            foreach (Player p in PropHuntPlayers)
            {
                if (p.IdleTime.TotalSeconds < 7)
                {
                    continue;
                }

                if (!(p.IdleTime.TotalSeconds >= 7))
                {
                    continue;
                }
                if (p.IsSolidBlock || p.IsPropHuntSeeker)
                {
                    continue;
                }
                p.Info.IsHidden = true;
                p.IsSolidBlock  = true;

                //Gets the coords of the player
                short    x   = (short)(p.Position.X / 32 * 32 + 16);
                short    y   = (short)(p.Position.Y / 32 * 32 + 16);
                short    z   = (short)(p.Position.Z / 32 * 32);
                Vector3I Pos = new Vector3I(p.Position.X / 32, p.Position.Y / 32, (p.Position.Z - 32) / 32);

                //Saves the player pos when they were solid for later removing the block
                p.prophuntSolidPos = Pos;

                //Converts player's model block into Block.*blockname*
                Block playerBlock = Map.GetBlockByName(p.Model);

                //Places the block at the players current location
                var blockUpdate = new BlockUpdate(null, Pos, playerBlock);
                if (p.World != null)
                {
                    if (p.World.Map != null)
                    {
                        p.World.Map.QueueUpdate(blockUpdate);
                    }
                }
                p.WorldMap.SetBlock(Pos, playerBlock);

                p.Message("&cYou are now a solid block. Don't move!");
            }
        }
Example #6
0
        public void ProcessUpdates()
        {
            if (World.IsLocked)
            {
                if (World.PendingUnload)
                {
                    World.UnloadMap(true);
                }
                return;
            }

            int         packetsSent         = 0;
            int         maxPacketsPerUpdate = Server.CalculateMaxPacketsPerUpdate(World);
            BlockUpdate update = new BlockUpdate();

            while (packetsSent < maxPacketsPerUpdate)
            {
                if (!updates.Dequeue(ref update))
                {
                    if (World.IsFlushing)
                    {
                        World.EndFlushMapBuffer();
                    }
                    break;
                }
                ChangedSinceSave = true;
                if (!InBounds(update.X, update.Y, update.H))
                {
                    continue;
                }
                int blockIndex = Index(update.X, update.Y, update.H);
                Blocks[blockIndex] = update.BlockType; // TODO: investigate IndexOutOfRangeException here

                if (!World.IsFlushing)
                {
                    World.SendToAllDelayed(PacketWriter.MakeSetBlock(update.X, update.Y, update.H, update.BlockType), update.Origin);
                }
                packetsSent++;
            }

            if (packetsSent == 0 && World.PendingUnload)
            {
                World.UnloadMap(true);
            }
        }
Example #7
0
        // Avoid re-defining the list every time your handler is called. Make it static!
        public static void PlayerClickingHandler(object sender, Events.PlayerClickingEventArgs e)
        {
            if (!e.Player.IsPropHuntSeeker)
            {
                return;
            }
            // if player clicked a non-air block
            if (e.Action != ClickAction.Delete)
            {
                return;
            }
            Block currentBlock = e.Player.WorldMap.GetBlock(e.Coords); // Gets the blocks coords

            // Check if currentBlock is on the list
            if (!clickableBlocks.Contains(currentBlock))
            {
                return;
            }
            foreach (Player p in PropHuntPlayers.Where(p => p.prophuntSolidPos == e.Coords && p.IsSolidBlock))
            {
                //Remove the players block
                const Block airBlock    = Block.Air;
                var         blockUpdate = new BlockUpdate(null, p.prophuntSolidPos, airBlock);
                if (p.World != null)
                {
                    if (p.World.Map != null)
                    {
                        p.World.Map.QueueUpdate(blockUpdate);
                    }
                }

                //Do the other stuff
                p.Message("&cA seeker has found you! Run away!");
                p.IsPropHuntTagged = true;
                p.ResetIdleTimer();
                p.IsSolidBlock  = false;
                p.Info.IsHidden = false;
                Player.RaisePlayerHideChangedEvent(p);
            }
        }
Example #8
0
 private static void PlaceHandler(Player player, CommandReader cmd) {
     bool isConsole = (player == Player.Console);
     if (isConsole && cmd.Count < 6) {
         player.Message("When used by console /Place requires a world name.");
         player.Message("/Place [x] [y] [z] [block] [world]");
         return;
     }
     Block block = Block.Stone;
     if (!isConsole && player.LastUsedBlockType != Block.None)
     	block = player.LastUsedBlockType;
     Vector3I coords;
     int x, y, z;
     if (cmd.NextInt(out x) && cmd.NextInt(out y) && cmd.NextInt(out z)) {
         if (cmd.HasNext) {
             string last = cmd.Next();
             if (!Map.GetBlockByName(last, false, out block)) {
                 player.Message("\"{0}\" is not a valid block type", last);
                 return;
             }
         }
         coords = new Vector3I(x, y, z);
     } else if (isConsole) {
         player.Message("Invalid coordinates!");
         return;
     } else {
         cmd.Rewind();
         if (cmd.HasNext) {
             string last = cmd.Next();
             if (!Map.GetBlockByName(last, false, out block)) {
                 player.Message("\"{0}\" is not a valid block type", last);
                 return;
             }
         }
         coords = new Vector3I(player.Position.X / 32, player.Position.Y / 32, (player.Position.Z - 64) / 32);
     }
     World world;
     if (player == Player.Console) {
         string worldName = cmd.Next();
         if (string.IsNullOrEmpty(worldName)) {
             player.Message("Console must specify a world!");
         }
         world = WorldManager.FindWorldOrPrintMatches(player, worldName);
         if (world == null)
             return;
     } else {
         world = player.World;
     }
     bool unLoad = false;
     if (!world.IsLoaded) {
         world.LoadMap();
         unLoad = true;
     }
     coords.X = Math.Min(world.map.Width - 1, Math.Max(0, coords.X));
     coords.Y = Math.Min(world.map.Length - 1, Math.Max(0, coords.Y));
     coords.Z = Math.Min(world.map.Height - 1, Math.Max(0, coords.Z));
     
     if (player == Player.Console) {
         BlockUpdate blockUpdate = new BlockUpdate(player, coords, block);
         player.Info.ProcessBlockPlaced((byte)block);
         world.map.QueueUpdate(blockUpdate);
         player.RaisePlayerPlacedBlockEvent(player, world.map, coords, block, world.map.GetBlock(coords), BlockChangeContext.Manual, true);
     } else {
         player.SendNow(Packet.MakeSetBlock(coords, block, player));
         player.PlaceBlockWithEvents(coords, ClickAction.Build, block);
     }
     if (!isConsole) 
         player.Message("{0} placed at {1}", block.ToString(), coords.ToString());
     if (unLoad) {
         world.UnloadMap(true);
     }
 }
Example #9
0
        protected override int PerformInternal()
        {
            //lock is done already
            if (Block.Undefined == _prevBlock)            //created out of bounds, dont continue
            {
                return(0);
            }
            //fix for portal gun
            if (_owner.orangePortal.Count > 0)
            {
                if (_pos == _owner.orangePortal[0] || _pos == _owner.orangePortal[1])
                {
                    return(0);
                }
            }
            if (_owner.bluePortal.Count > 0)
            {
                if (_pos == _owner.bluePortal[0] || _pos == _owner.bluePortal[1])
                {
                    return(0);
                }
            }

            //delete at the previous position, restore water unconditionally, lava only when bullet is still there to prevent restoration of explosion lava
            if (_prevBlock != Block.Water)
            {
                _prevBlock = _map.GetBlock(_pos) == _block ?                     //is the bullet still here
                             (_prevBlock == Block.Lava ? Block.Lava : Block.Air) //yes, then either restore lava or set air
                                        : Block.Undefined;                       //no, it was removed by some other process, do nothing then
            }
            if (Block.Undefined != _prevBlock)
            {
                UpdateMap(new BlockUpdate(null, _pos, _prevBlock));
            }

            List <BlockUpdate> updates = new List <BlockUpdate>();

            for (int i = 0; i < _behavior.MovesPerProcessingStep && _restDistance > 0; ++i)
            {
                _pos       = Move();
                _prevBlock = _map.GetBlock(_pos);

                if (Block.Undefined == _prevBlock)
                {
                    _restDistance = 0;
                    break;
                }

                _behavior.ModifyDirection(ref _direction, _prevBlock);                 //e.g. if you want it to be dependent on gravity or change direction depending on current block etc

                if (_behavior.VisitBlock(_world, _pos, _prevBlock, _owner, ref _restDistance, updates, _block) && _behavior.CanKillPlayer)
                {
                    CheckHitPlayers(updates);
                }
            }

            bool cont = _restDistance > 0;

            if (cont)            //check if the last update was for the current position and replace it with the particle
            {
                int idx = updates.Count - 1;
                if (idx >= 0 && updates[idx].X == _pos.X &&
                    updates[idx].Y == _pos.Y &&
                    updates[idx].Z == _pos.Z)
                {
                    updates[idx] = new BlockUpdate(null, _pos, _block);
                }
                else
                {
                    updates.Add(new BlockUpdate(null, _pos, _block));
                }
            }

            for (int i = 0; i < updates.Count; ++i)
            {
                UpdateMap(updates[i]);
            }

            return(cont ? _stepDelay : 0);
        }
Example #10
0
        static void Place(Player player, Command cmd)
        {
            Block block;
            if (player.LastUsedBlockType == Block.Undefined)
            {
                block = Block.Stone;
            }
            else
            {
                block = player.LastUsedBlockType;
            }
            Vector3I Pos = new Vector3I(player.Position.X / 32, player.Position.Y / 32, (player.Position.Z / 32) - 2);

            if (player.CanPlace(player.World.Map, Pos, player.GetBind(block), BlockChangeContext.Manual) != CanPlaceResult.Allowed)
            {
                player.Message("&WYou are not allowed to build here");
                return;
            }

            Player.RaisePlayerPlacedBlockEvent(player, player.WorldMap, Pos, player.WorldMap.GetBlock(Pos), block, BlockChangeContext.Manual);
            BlockUpdate blockUpdate = new BlockUpdate(null, Pos, block);
            player.World.Map.QueueUpdate(blockUpdate);
            player.Message("Block placed below your feet");
        }
Example #11
0
        private static void DisPlace(Player player, CommandReader cmd) {
            Block block;
            if (cmd.Count <= 2) {
                player.Message(CdDisPlace.Usage);
                return;
            }
            string tryBlock = cmd.Next();
            if (!Map.GetBlockByName(tryBlock, false, out block)) {
                player.Message("Invalid block name/id: {0}", tryBlock);
                return;
            }
            int dis;
            string tryInt = cmd.Next();
            if (!int.TryParse(tryInt, out dis)) {
                player.Message("Invalid distance: {0}", tryInt);
                return;
            }
            dis = dis*32;
            byte rot = player.Position.R;
            byte ud = player.Position.L;
            if (225 < ud || ud < 32) {
                if (225 <= rot || rot <= 32) {
                    Vector3I Pos = new Vector3I(player.Position.X/32, (player.Position.Y - dis)/32,
                        (player.Position.Z - 32)/32);
                    Pos.X = Math.Min(player.WorldMap.Width - 1, Math.Max(0, Pos.X));
                    Pos.Y = Math.Min(player.WorldMap.Length - 1, Math.Max(0, Pos.Y));
                    Pos.Z = Math.Min(player.WorldMap.Height - 1, Math.Max(0, Pos.Z));

                    if (player.CanPlace(player.World.Map, Pos, block, BlockChangeContext.Drawn) !=
                        CanPlaceResult.Allowed) {
                        player.Message("&WYou are not allowed to build here");
                        return;
                    }

                    Player.RaisePlayerPlacedBlockEvent(player, player.WorldMap, Pos, player.WorldMap.GetBlock(Pos),
                        block, BlockChangeContext.Drawn);
                    BlockUpdate blockUpdate = new BlockUpdate(null, Pos, block);
                    player.World.Map.QueueUpdate(blockUpdate);
                    player.Message("Block placed at {0} ({1} blocks away from you)", Pos, dis/32);
                } else if (33 <= rot && rot <= 96) {
                    Vector3I Pos = new Vector3I((player.Position.X + dis)/32, player.Position.Y/32,
                        (player.Position.Z - 32) / 32);
                    Pos.X = Math.Min(player.WorldMap.Width - 1, Math.Max(0, Pos.X));
                    Pos.Y = Math.Min(player.WorldMap.Length - 1, Math.Max(0, Pos.Y));
                    Pos.Z = Math.Min(player.WorldMap.Height - 1, Math.Max(0, Pos.Z));

                    if (player.CanPlace(player.World.Map, Pos, block, BlockChangeContext.Drawn) !=
                        CanPlaceResult.Allowed) {
                        player.Message("&WYou are not allowed to build here");
                        return;
                    }

                    Player.RaisePlayerPlacedBlockEvent(player, player.WorldMap, Pos, player.WorldMap.GetBlock(Pos),
                        block, BlockChangeContext.Drawn);
                    BlockUpdate blockUpdate = new BlockUpdate(null, Pos, block);
                    player.World.Map.QueueUpdate(blockUpdate);
                    player.Message("Block placed at {0} ({1} blocks away from you)", Pos, dis/32);
                } else if (97 <= rot && rot <= 160) {
                    Vector3I Pos = new Vector3I(player.Position.X/32, (player.Position.Y + dis)/32,
                        (player.Position.Z - 32) / 32);
                    Pos.X = Math.Min(player.WorldMap.Width - 1, Math.Max(0, Pos.X));
                    Pos.Y = Math.Min(player.WorldMap.Length - 1, Math.Max(0, Pos.Y));
                    Pos.Z = Math.Min(player.WorldMap.Height - 1, Math.Max(0, Pos.Z));

                    if (player.CanPlace(player.World.Map, Pos, block, BlockChangeContext.Drawn) !=
                        CanPlaceResult.Allowed) {
                        player.Message("&WYou are not allowed to build here");
                        return;
                    }

                    Player.RaisePlayerPlacedBlockEvent(player, player.WorldMap, Pos, player.WorldMap.GetBlock(Pos),
                        block, BlockChangeContext.Drawn);
                    BlockUpdate blockUpdate = new BlockUpdate(null, Pos, block);
                    player.World.Map.QueueUpdate(blockUpdate);
                    player.Message("Block placed at {0} ({1} blocks away from you)", Pos, dis/32);
                } else if (161 <= rot && rot <= 224) {
                    Vector3I Pos = new Vector3I((player.Position.X - dis)/32, player.Position.Y/32,
                        (player.Position.Z - 32) / 32);
                    Pos.X = Math.Min(player.WorldMap.Width - 1, Math.Max(0, Pos.X));
                    Pos.Y = Math.Min(player.WorldMap.Length - 1, Math.Max(0, Pos.Y));
                    Pos.Z = Math.Min(player.WorldMap.Height - 1, Math.Max(0, Pos.Z));

                    if (player.CanPlace(player.World.Map, Pos, block, BlockChangeContext.Drawn) !=
                        CanPlaceResult.Allowed) {
                        player.Message("&WYou are not allowed to build here");
                        return;
                    }

                    Player.RaisePlayerPlacedBlockEvent(player, player.WorldMap, Pos, player.WorldMap.GetBlock(Pos),
                        block, BlockChangeContext.Drawn);
                    BlockUpdate blockUpdate = new BlockUpdate(null, Pos, block);
                    player.World.Map.QueueUpdate(blockUpdate);
                    player.Message("Block placed at {0} ({1} blocks away from you)", Pos, dis/32);
                } else {
                    player.Message("Error occurred, please try again.");
                    return;
                }
            } else {
                if (192 <= ud && ud <= 224) {
                    Vector3I Pos = new Vector3I(player.Position.X/32, player.Position.Y/32,
                        (player.Position.Z - 32 + dis) / 32);
                    Pos.X = Math.Min(player.WorldMap.Width - 1, Math.Max(0, Pos.X));
                    Pos.Y = Math.Min(player.WorldMap.Length - 1, Math.Max(0, Pos.Y));
                    Pos.Z = Math.Min(player.WorldMap.Height - 1, Math.Max(0, Pos.Z));

                    if (player.CanPlace(player.World.Map, Pos, block, BlockChangeContext.Drawn) !=
                        CanPlaceResult.Allowed) {
                        player.Message("&WYou are not allowed to build here");
                        return;
                    }

                    Player.RaisePlayerPlacedBlockEvent(player, player.WorldMap, Pos, player.WorldMap.GetBlock(Pos),
                        block, BlockChangeContext.Drawn);
                    BlockUpdate blockUpdate = new BlockUpdate(null, Pos, block);
                    player.World.Map.QueueUpdate(blockUpdate);
                    player.Message("Block placed at {0} ({1} blocks away from you)", Pos, dis / 32);
                } else if (33 <= ud && ud <= 65) {
                    Vector3I Pos = new Vector3I(player.Position.X/32, player.Position.Y/32,
                        (player.Position.Z - 32 - dis) / 32);
                    Pos.X = Math.Min(player.WorldMap.Width - 1, Math.Max(0, Pos.X));
                    Pos.Y = Math.Min(player.WorldMap.Length - 1, Math.Max(0, Pos.Y));
                    Pos.Z = Math.Min(player.WorldMap.Height - 1, Math.Max(0, Pos.Z));

                    if (player.CanPlace(player.World.Map, Pos, block, BlockChangeContext.Drawn) !=
                        CanPlaceResult.Allowed) {
                        player.Message("&WYou are not allowed to build here");
                        return;
                    }

                    Player.RaisePlayerPlacedBlockEvent(player, player.WorldMap, Pos, player.WorldMap.GetBlock(Pos),
                        block, BlockChangeContext.Drawn);
                    BlockUpdate blockUpdate = new BlockUpdate(null, Pos, block);
                    player.World.Map.QueueUpdate(blockUpdate);
                    player.Message("Block placed at {0} ({1} blocks away from you)", Pos, dis/32);
                } else {
                    player.Message("Error occurred, please try again.");
                    return;
                }
            }
        }
Example #12
0
        // Applies pending updates and sends them to players (if applicable).
        internal void ProcessUpdates() {
            if( World == null ) {
                throw new InvalidOperationException( "Map must be assigned to a world to process updates." );
            }

            if( World.IsLocked ) {
                if( World.IsPendingMapUnload ) {
                    World.UnloadMap( true );
                }
                return;
            }

            int packetsSent = 0;
            bool canFlush = false;
            int maxPacketsPerUpdate = Server.CalculateMaxPacketsPerUpdate( World );
            BlockUpdate update = new BlockUpdate();
            while( packetsSent < maxPacketsPerUpdate ) {
                if( !updates.TryDequeue( out update ) ) {
                    if( World.IsFlushing ) {
                        canFlush = true;
                    }
                    break;
                }
                HasChangedSinceSave = true;
                compressedCopyCache = null;
                if( !InBounds( update.X, update.Y, update.Z ) ) continue;
                int blockIndex = Index( update.X, update.Y, update.Z );
                Blocks[blockIndex] = (byte)update.BlockType;

                if( !World.IsFlushing ) {
                	Player[] players = World.Players;
                	for( int i = 0; i < players.Length; i++ ) {
                		// cannot reuse packet as each player may require different modifications to block field
                		Player p = players[i];
                		if (p == update.Origin) 
                			continue;
                		Packet packet = Packet.MakeSetBlock(new Vector3I(update.X, update.Y, update.Z), update.BlockType, p);
                		p.SendLowPriority( packet );
                	}
                }
                packetsSent++;
            }

            if( drawOps.Count > 0 ) {
                lock( drawOpLock ) {
                    if( drawOps.Count > 0 ) {
                        packetsSent += ProcessDrawOps( maxPacketsPerUpdate - packetsSent );
                    }
                }
            } else if( canFlush ) {
                World.EndFlushMapBuffer();
            }

            if( packetsSent == 0 && World.IsPendingMapUnload ) {
                World.UnloadMap( true );
            }
        }
Example #13
0
        // Applies pending updates and sends them to players (if applicable).
        internal void ProcessUpdates()
        {
            if (World == null)
            {
                throw new InvalidOperationException("Map must be assigned to a world to process updates.");
            }

            if (World.IsLocked)
            {
                if (World.IsPendingMapUnload)
                {
                    World.UnloadMap(true);
                }
                return;
            }

            int         packetsSent         = 0;
            bool        canFlush            = false;
            int         maxPacketsPerUpdate = Server.CalculateMaxPacketsPerUpdate(World);
            BlockUpdate update = new BlockUpdate();

            while (packetsSent < maxPacketsPerUpdate)
            {
                if (!updates.Dequeue(ref update))
                {
                    if (World.IsFlushing)
                    {
                        canFlush = true;
                    }
                    break;
                }
                HasChangedSinceSave = true;
                compressedCopyCache = null;
                if (!InBounds(update.X, update.Y, update.Z))
                {
                    continue;
                }
                int blockIndex = Index(update.X, update.Y, update.Z);
                Blocks[blockIndex] = (byte)update.BlockType;

                if (!World.IsFlushing)
                {
                    Packet packet = PacketWriter.MakeSetBlock(update.X, update.Y, update.Z, update.BlockType);
                    World.Players.SendLowPriority(update.Origin, packet);
                }
                packetsSent++;
            }

            if (drawOps.Count > 0)
            {
                lock ( drawOpLock ) {
                    if (drawOps.Count > 0)
                    {
                        packetsSent += ProcessDrawOps(maxPacketsPerUpdate - packetsSent);
                    }
                }
            }
            else if (canFlush)
            {
                World.EndFlushMapBuffer();
            }

            if (packetsSent == 0 && World.IsPendingMapUnload)
            {
                World.UnloadMap(true);
            }
        }
Example #14
0
 public bool FireChangedBlockEvent( ref BlockUpdate update )
 {
     bool cancel = false;
     if ( OnPlayerChangedBlock != null ) {
         OnPlayerChangedBlock( this, ref update, ref cancel );
     }
     return !cancel;
 }
Example #15
0
        //hitted? jonty I thought you were better than that :(
        public void HitPlayer(World world, Vector3I pos, Player hitted, Player by, ref int restDistance, IList<BlockUpdate> updates)
        {
            //Capture the flag
            if (by.Info.isPlayingCTF)
            {
                //Friendly fire
                if ((hitted.Info.CTFBlueTeam && by.Info.CTFBlueTeam) || (hitted.Info.CTFRedTeam && by.Info.CTFRedTeam))
                {
                    by.Message("{0} is on your team!", hitted.Name);
                    return;
                }

                if (hitted.Info.canDodge)
                {
                    int dodgeChance = (new Random()).Next(0, 2);
                    if (dodgeChance == 0)
                    {
                        by.Message("{0} dodged your attack!", hitted.Name);
                        return;
                    }
                }
                //Take the hit, one in ten chance of a critical hit which does 50 damage instead of 25
                int critical = (new Random()).Next(0, 9);

                if (critical == 0)
                {
                    if (by.Info.strengthened)//critical by a strengthened enemy instantly kills
                    {
                        hitted.Info.Health = 0;
                    }
                    else
                    {
                        hitted.Info.Health -= 50;
                    }
                    world.Players.Message("{0} landed a critical shot on {1}!", by.Name, hitted.Name);
                }
                else
                {
                    if (by.Info.strengthened)
                    {
                        hitted.Info.Health -= 50;
                    }
                    else
                    {
                        hitted.Info.Health -= 25;
                    }
                }

                //Create epic ASCII Health Bar

                string healthBar = "&f[&a--------&f]";
                if (hitted.Info.Health == 75)
                {
                    healthBar = "&f[&a------&8--&f]";
                }
                else if (hitted.Info.Health == 50)
                {
                    healthBar = "&f[&e----&8----&f]";
                }
                else if (hitted.Info.Health == 25)
                {
                    healthBar = "&f[&c--&8------&f]";
                }
                else if(hitted.Info.Health <= 0)
                {
                    healthBar = "&f[&8--------&f]";
                }

                if (hitted.ClassiCube && Heartbeat.ClassiCube())
                {
                    hitted.Send(PacketWriter.MakeSpecialMessage((byte)1, healthBar));
                }
                else
                {
                    hitted.Message("You have " + hitted.Info.Health.ToString() + " health.");
                }

                //If the hit player's health is 0 or less, they die
                if (hitted.Info.Health <= 0)
                {

                    hitted.KillCTF(world, String.Format("&f{0}&S was shot by &f{1}", hitted.Name, by.Name));
                    CTF.PowerUp(by);
                    hitted.Info.CTFKills++;

                    if (hitted.Info.hasRedFlag)
                    {
                        world.Players.Message("The red flag has been returned.");
                        hitted.Info.hasRedFlag = false;

                        //Put flag back
                        BlockUpdate blockUpdate = new BlockUpdate(null, world.redFlag, Block.Red);
                        foreach (Player p in world.Players)
                        {
                            p.World.Map.QueueUpdate(blockUpdate);
                        }
                        world.redFlagTaken = false;

                    }

                    if (hitted.Info.hasBlueFlag)
                    {
                        world.Players.Message("The blue flag has been returned.");
                        hitted.Info.hasBlueFlag = false;

                        //Put flag back
                        BlockUpdate blockUpdate = new BlockUpdate(null, world.blueFlag, Block.Blue);
                        foreach (Player p in world.Players)
                        {
                            p.World.Map.QueueUpdate(blockUpdate);
                        }
                        world.blueFlagTaken = false;
                    }

                    //revive dead players with 100% health
                    hitted.Info.Health = 100;

                    if (hitted.ClassiCube && Heartbeat.ClassiCube())
                    {
                        hitted.Send(PacketWriter.MakeSpecialMessage((byte)1, "&f[&a--------&f]"));
                    }
                    else
                    {
                        hitted.Message("You have 100 health.");
                    }
                }

                return;
            }

            //TDM and FFA
            if ((hitted.Info.isOnBlueTeam && by.Info.isOnBlueTeam) || (hitted.Info.isOnRedTeam && by.Info.isOnRedTeam))
            {
                by.Message("{0} is on your team!", hitted.ClassyName);
            }
            else
            {

                //Take the hit, one in ten chance of a critical hit which does 50 damage instead of 25
                int critical = (new Random()).Next(0, 9);

                if (critical == 0)
                {
                    hitted.Info.Health -= 50;
                    world.Players.Message("{0} landed a critical shot on {1}!", by.Name, hitted.Name);
                }
                else
                {
                    hitted.Info.Health -= 25;
                }

                if (hitted.Info.Health < 0)
                {
                    hitted.Info.Health = 0;
                }

                //Create epic ASCII Health Bar

                string healthBar = "&f[&a--------&f]";
                if (hitted.Info.Health == 75)
                {
                    healthBar = "&f[&a------&8--&f]";
                }
                else if (hitted.Info.Health == 50)
                {
                    healthBar = "&f[&e----&8----&f]";
                }
                else if (hitted.Info.Health == 25)
                {
                    healthBar = "&f[&c--&8------&f]";
                }
                else
                {
                    healthBar = "&f[&8--------&f]";
                }
                hitted.Send(PacketWriter.MakeSpecialMessage((byte)1, healthBar));
                if (hitted.ClassiCube && Heartbeat.ClassiCube())
                {
                    hitted.Send(PacketWriter.MakeSpecialMessage((byte)1, healthBar));
                }
                else
                {
                    hitted.Message("You have " + hitted.Info.Health.ToString() + " health.");
                }

                if (hitted.Info.Health == 0)
                {

                    hitted.Kill(world, String.Format("{0}&S was shot by {1}", hitted.ClassyName, hitted.ClassyName == by.ClassyName ? "theirself" : by.ClassyName));
                    updates.Add(new BlockUpdate(null, pos, Block.Air));
                    restDistance = 0;

                    //TDM
                    if (fCraft.TeamDeathMatch.isOn)
                    {
                        if (hitted.Info.isPlayingTD && hitted.Info.isOnBlueTeam && by.Info.isPlayingTD) //if the player is playing TD and on blue team, +1 for Red Team Score
                        {
                            fCraft.TeamDeathMatch.redScore++;
                            hitted.Info.gameDeaths++;
                            hitted.Info.totalDeathsTDM++;
                            by.Info.gameKills++;
                            by.Info.totalKillsTDM++;
                        }
                        if (hitted.Info.isPlayingTD && hitted.Info.isOnRedTeam && by.Info.isPlayingTD) //if the player is playing TD and on blue team, +1 for Red Team Score
                        {
                            fCraft.TeamDeathMatch.blueScore++;
                            hitted.Info.gameDeaths++;       //counts the individual players deaths
                            hitted.Info.totalDeathsTDM++;   //tallies total TDM deaths (never gets reset)
                            by.Info.gameKills++;            //counts the individual players amount of kills
                            by.Info.totalKillsTDM++;        //tallies total TDM kills
                        }

                        //update scoreboard for all players
                        foreach (Player p in hitted.World.Players)
                        {
                            if (p.ClassiCube && Heartbeat.ClassiCube())
                            {
                                p.Send(PacketWriter.MakeSpecialMessage((byte)2, "&cRed&f: " + fCraft.TeamDeathMatch.redScore + ",&1 Blue&f: " + fCraft.TeamDeathMatch.blueScore));
                            }
                            else
                            {
                                p.Message("The score is now &cRed&f: " + fCraft.TeamDeathMatch.redScore + ",&1 Blue&f: " + fCraft.TeamDeathMatch.blueScore);
                            }
                        }
                    }

                    //FFA
                    if (FFA.isOn())
                    {
                        if (hitted.Info.isPlayingFFA && by.Info.isPlayingFFA) //if the player is playing FFA and the person they hit is also playing
                        {
                            hitted.Info.gameDeathsFFA++;
                            hitted.Info.totalDeathsFFA++;
                            by.Info.gameKillsFFA++;
                            by.Info.totalKillsFFA++;
                        }

                        //find current kill leader
                        Player leader = new Player("");//create a temp pseudo player
                        int kills = 0;

                        foreach (Player p in hitted.World.Players)
                        {
                            if (p.Info.gameKillsFFA > kills)
                            {
                                kills = p.Info.gameKillsFFA;
                                leader = p;
                            }
                        }
                        foreach (Player p in hitted.World.Players)
                        {
                            if (p.ClassiCube && Heartbeat.ClassiCube())
                            {
                                p.Send(PacketWriter.MakeSpecialMessage((byte)2, "&eCurrent Leader&f: " + leader.Name + ", Kills: " + leader.Info.gameKillsFFA));
                            }
                        }
                    }

                    //revive dead players with 100% health
                    hitted.Info.Health = 100;

                    if (hitted.ClassiCube && Heartbeat.ClassiCube())
                    {
                        hitted.Send(PacketWriter.MakeSpecialMessage((byte)1, "&f[&a--------&f]"));
                    }
                    else
                    {
                        hitted.Message("You have " + hitted.Info.Health.ToString() + "health.");
                    }
                }
            }
        }
Example #16
0
 internal void QueueUpdate(BlockUpdate update)
 {
     lock ( queueLock ) {
         updates.Enqueue(update);
     }
 }
Example #17
0
        public static void PlayerClicked(object sender, PlayerClickedEventArgs e)
        {
            if (GameManager.GameIsOn)
            {
                if (e.Player.World.Equals(GameManager.GameWorld))
                {
                    Zone[] allowed, denied;
                    if (e.Player.WorldMap.Zones.CheckDetailed(e.Coords, e.Player, out allowed, out denied))
                    {
                        foreach (Zone zone in allowed)
                        {
                            if (zone.Name.EndsWith("redbase1"))
                            {
                                if (GameManager.BlueTeam.Contains(e.Player))
                                {
                                    BlockUpdate update = new BlockUpdate(null, e.Coords, Block.Red);
                                    e.Player.World.Map.QueueUpdate(update);
                                    Red1Click++;
                                    if (Red1Click > 29)
                                    {
                                        CaptureBase(zone, e.Player);
                                        Red1Click = 0;
                                        zone.Name = "bluecaptured1";
                                        e.Player.World.Players.Message("The &9Blue Team &Scaptured &CRed Base 1");
                                        GameManager.BlueBaseCount++;
                                        GameManager.RedBaseCount--;
                                    }
                                }

                                if (GameManager.RedTeam.Contains(e.Player))
                                {
                                    BlockUpdate update = new BlockUpdate(null, e.Coords, Block.Red);
                                    e.Player.World.Map.QueueUpdate(update);
                                    if (Red1Click > 0)
                                        Red1Click--;
                                }
                            }

                            if (zone.Name.EndsWith("bluecaptured1"))
                            {
                                if (GameManager.RedTeam.Contains(e.Player))
                                {
                                    BlockUpdate update = new BlockUpdate(null, e.Coords, Block.Blue);
                                    e.Player.World.Map.QueueUpdate(update);
                                    BlueCapturedClick++;
                                    if (BlueCapturedClick > 29)
                                    {
                                        CaptureBase(zone, e.Player);
                                        BlueCapturedClick = 0;
                                        zone.Name = "redbase1";
                                        e.Player.World.Players.Message("The &CRed Team &Stook back &CRed Base 1");
                                        GameManager.BlueBaseCount--;
                                        GameManager.RedBaseCount++;
                                    }
                                }

                                if (GameManager.BlueTeam.Contains(e.Player))
                                {
                                    BlockUpdate update = new BlockUpdate(null, e.Coords, Block.Blue);
                                    e.Player.World.Map.QueueUpdate(update);
                                    if (BlueCapturedClick > 0)
                                        BlueCapturedClick--;
                                }
                            }

                            //--------------------
                            if (zone.Name.EndsWith("redbase2"))
                            {
                                if (GameManager.BlueTeam.Contains(e.Player))
                                {
                                    BlockUpdate update = new BlockUpdate(null, e.Coords, Block.Red);
                                    e.Player.World.Map.QueueUpdate(update);
                                    Red2Click++;
                                    if (Red2Click > 29)
                                    {
                                        CaptureBase(zone, e.Player);
                                        Red2Click = 0;
                                        zone.Name = "bluecaptured2";
                                        e.Player.World.Players.Message("The &9Blue Team &Scaptured &CRed Base 2");
                                        GameManager.BlueBaseCount++;
                                        GameManager.RedBaseCount--;
                                    }
                                }

                                if (GameManager.RedTeam.Contains(e.Player))
                                {
                                    BlockUpdate update = new BlockUpdate(null, e.Coords, Block.Red);
                                    e.Player.World.Map.QueueUpdate(update);
                                    if (Red2Click > 0)
                                        Red2Click--;
                                }
                            }

                            if (zone.Name.EndsWith("bluecaptured2"))
                            {
                                if (GameManager.RedTeam.Contains(e.Player))
                                {
                                    BlockUpdate update = new BlockUpdate(null, e.Coords, Block.Blue);
                                    e.Player.World.Map.QueueUpdate(update);
                                    BlueCapturedClick2++;
                                    if (BlueCapturedClick2 > 29)
                                    {
                                        CaptureBase(zone, e.Player);
                                        BlueCapturedClick2 = 0;
                                        zone.Name = "redbase2";
                                        e.Player.World.Players.Message("The &CRed Team &Stook back &CRed Base 2");
                                        GameManager.BlueBaseCount--;
                                        GameManager.RedBaseCount++;
                                    }
                                }

                                if (GameManager.BlueTeam.Contains(e.Player))
                                {
                                    BlockUpdate update = new BlockUpdate(null, e.Coords, Block.Blue);
                                    e.Player.World.Map.QueueUpdate(update);
                                    if (BlueCapturedClick2 > 0)
                                        BlueCapturedClick2--;
                                }
                            }

                            //---------------
                            if (zone.Name.EndsWith("redbase3"))
                            {
                                if (GameManager.BlueTeam.Contains(e.Player))
                                {
                                    BlockUpdate update = new BlockUpdate(null, e.Coords, Block.Red);
                                    e.Player.World.Map.QueueUpdate(update);
                                    Red3Click++;
                                    if (Red3Click > 29)
                                    {
                                        CaptureBase(zone, e.Player);
                                        Red3Click = 0;
                                        zone.Name = "bluecaptured3";
                                        e.Player.World.Players.Message("The &9Blue Team &Scaptured &CRed Base 3");
                                        GameManager.BlueBaseCount++;
                                        GameManager.RedBaseCount--;
                                    }
                                }

                                if (GameManager.RedTeam.Contains(e.Player))
                                {
                                    BlockUpdate update = new BlockUpdate(null, e.Coords, Block.Red);
                                    e.Player.World.Map.QueueUpdate(update);
                                    if (Red3Click > 0)
                                        Red3Click--;
                                }
                            }

                            if (zone.Name.EndsWith("bluecaptured3"))
                            {
                                if (GameManager.RedTeam.Contains(e.Player))
                                {
                                    BlockUpdate update = new BlockUpdate(null, e.Coords, Block.Blue);
                                    e.Player.World.Map.QueueUpdate(update);
                                    BlueCapturedClick3++;
                                    if (BlueCapturedClick3 > 29)
                                    {
                                        CaptureBase(zone, e.Player);
                                        BlueCapturedClick3 = 0;
                                        zone.Name = "redbase3";
                                        e.Player.World.Players.Message("The &CRed Team &Stook back &CRed Base 2");
                                        GameManager.BlueBaseCount--;
                                        GameManager.RedBaseCount++;
                                    }
                                }

                                if (GameManager.BlueTeam.Contains(e.Player))
                                {
                                    BlockUpdate update = new BlockUpdate(null, e.Coords, Block.Blue);
                                    e.Player.World.Map.QueueUpdate(update);
                                    if (BlueCapturedClick3 > 0)
                                        BlueCapturedClick3--;
                                }
                            }

                            //----------blue----------

                            if (zone.Name.EndsWith("bluebase1"))
                            {
                                if (GameManager.RedTeam.Contains(e.Player))
                                {
                                    BlockUpdate update = new BlockUpdate(null, e.Coords, Block.Blue);
                                    e.Player.World.Map.QueueUpdate(update);
                                    Blue1Click++;
                                    if (Blue1Click > 29)
                                    {
                                        CaptureBase(zone, e.Player);
                                        Blue1Click = 0;
                                        zone.Name = "redcaptured1";
                                        e.Player.World.Players.Message("The &CRed Team &Scaptured &9Blue Base 1");
                                        GameManager.BlueBaseCount--;
                                        GameManager.RedBaseCount++;
                                    }
                                }

                                if (GameManager.BlueTeam.Contains(e.Player))
                                {
                                    BlockUpdate update = new BlockUpdate(null, e.Coords, Block.Blue);
                                    e.Player.World.Map.QueueUpdate(update);
                                    if (Blue1Click > 0)
                                        Blue1Click--;
                                }
                            }

                            if (zone.Name.EndsWith("redcaptured1"))
                            {
                                if (GameManager.BlueTeam.Contains(e.Player))
                                {
                                    BlockUpdate update = new BlockUpdate(null, e.Coords, Block.Red);
                                    e.Player.World.Map.QueueUpdate(update);
                                    RedCapturedClick++;
                                    if (RedCapturedClick > 29)
                                    {
                                        CaptureBase(zone, e.Player);
                                        RedCapturedClick = 0;
                                        zone.Name = "bluebase1";
                                        e.Player.World.Players.Message("The &9Blue Team &Stook back &9Blue Base 1");
                                        GameManager.BlueBaseCount++;
                                        GameManager.RedBaseCount--;
                                    }
                                }

                                if (GameManager.RedTeam.Contains(e.Player))
                                {
                                    BlockUpdate update = new BlockUpdate(null, e.Coords, Block.Red);
                                    e.Player.World.Map.QueueUpdate(update);
                                    if (RedCapturedClick > 0)
                                        RedCapturedClick--;
                                }
                            }

                            //--------------------
                            if (zone.Name.EndsWith("bluebase2"))
                            {
                                if (GameManager.RedTeam.Contains(e.Player))
                                {
                                    BlockUpdate update = new BlockUpdate(null, e.Coords, Block.Blue);
                                    e.Player.World.Map.QueueUpdate(update);
                                    Blue2Click++;
                                    if (Blue2Click > 29)
                                    {
                                        CaptureBase(zone, e.Player);
                                        Blue2Click = 0;
                                        zone.Name = "redcaptured2";
                                        e.Player.World.Players.Message("The &CRed Team &Scaptured &9Blue Base 2");
                                        GameManager.BlueBaseCount--;
                                        GameManager.RedBaseCount++;
                                    }
                                }

                                if (GameManager.BlueTeam.Contains(e.Player))
                                {
                                    BlockUpdate update = new BlockUpdate(null, e.Coords, Block.Blue);
                                    e.Player.World.Map.QueueUpdate(update);
                                    if (Blue2Click > 0)
                                        Blue2Click--;
                                }
                            }

                            if (zone.Name.EndsWith("redcaptured2"))
                            {
                                if (GameManager.BlueTeam.Contains(e.Player))
                                {
                                    BlockUpdate update = new BlockUpdate(null, e.Coords, Block.Red);
                                    e.Player.World.Map.QueueUpdate(update);
                                    RedCapturedClick2++;
                                    if (RedCapturedClick2 > 29)
                                    {
                                        CaptureBase(zone, e.Player);
                                        RedCapturedClick2 = 0;
                                        zone.Name = "bluebase2";
                                        e.Player.World.Players.Message("The &9Blue Team &Stook back &9Blue Base 2");
                                        GameManager.BlueBaseCount++;
                                        GameManager.RedBaseCount--;

                                    }
                                }

                                if (GameManager.RedTeam.Contains(e.Player))
                                {
                                    BlockUpdate update = new BlockUpdate(null, e.Coords, Block.Red);
                                    e.Player.World.Map.QueueUpdate(update);
                                    if (RedCapturedClick2 > 0)
                                        RedCapturedClick2--;
                                }
                            }

                            //---------------
                            if (zone.Name.EndsWith("bluebase3"))
                            {
                                if (GameManager.RedTeam.Contains(e.Player))
                                {
                                    BlockUpdate update = new BlockUpdate(null, e.Coords, Block.Blue);
                                    e.Player.World.Map.QueueUpdate(update);
                                    Blue3Click++;
                                    if (Blue3Click > 29)
                                    {
                                        CaptureBase(zone, e.Player);
                                        Blue3Click = 0;
                                        zone.Name = "redcaptured3";
                                        e.Player.World.Players.Message("The &CRed Team &Scaptured &9Blue Base 3");
                                        GameManager.BlueBaseCount--;
                                        GameManager.RedBaseCount++;
                                    }
                                }

                                if (GameManager.BlueTeam.Contains(e.Player))
                                {
                                    BlockUpdate update = new BlockUpdate(null, e.Coords, Block.Blue);
                                    e.Player.World.Map.QueueUpdate(update);
                                    if (Blue3Click > 0)
                                        Blue3Click--;
                                }
                            }

                            if (zone.Name.EndsWith("redcaptured3"))
                            {
                                if (GameManager.BlueTeam.Contains(e.Player))
                                {
                                    BlockUpdate update = new BlockUpdate(null, e.Coords, Block.Red);
                                    e.Player.World.Map.QueueUpdate(update);
                                    RedCapturedClick3++;
                                    if (RedCapturedClick3 > 29)
                                    {
                                        CaptureBase(zone, e.Player);
                                        RedCapturedClick3 = 0;
                                        zone.Name = "bluebase3";
                                        e.Player.World.Players.Message("The &9Blue Team &Stook back &9Blue Base 3");
                                        GameManager.BlueBaseCount++;
                                        GameManager.RedBaseCount--;
                                    }
                                }

                                if (GameManager.RedTeam.Contains(e.Player))
                                {
                                    BlockUpdate update = new BlockUpdate(null, e.Coords, Block.Red);
                                    e.Player.World.Map.QueueUpdate(update);
                                    if (RedCapturedClick3 > 0)
                                        RedCapturedClick3--;
                                }
                            }

                            else return;
                        }
                    }
                }
            }

            if (!GameManager.GameIsOn)
            {
                Zone[] allowed, denied;
                if (e.Player.WorldMap.Zones.CheckDetailed(e.Coords, e.Player, out allowed, out denied))
                {
                    foreach (Zone zone in allowed)
                    {
                        if (zone.Name.Contains("redbase"))
                        {
                            BlockUpdate update = new BlockUpdate(null, e.Coords, Block.Red);
                            e.Player.World.Map.QueueUpdate(update);
                        }

                        if (zone.Name.Contains("bluebase"))
                        {
                            BlockUpdate update = new BlockUpdate(null, e.Coords, Block.Blue);
                            e.Player.World.Map.QueueUpdate(update);
                        }
                    }
                }
            }
        }
Example #18
0
        // Handles building/deleting by the player
        public bool SetTile( short x, short y, short h, bool buildMode, Block type )
        {
            lastUsedBlockType = type;

            if( CheckBlockSpam() ) return true;

            if( world.isLocked ) {
                SendTileNow( x, y, h );
                return false;
            }

            /*if( world.lockDown ) { //TODO: streamload
                session.SendNow( PacketWriter.MakeSetBlock( x, y, h, world.map.GetBlock( x, y, h ) ) );
                Message( "Map is temporarily locked. Please wait." );
                return;
            }*/

            // check if player is too far away to legitimately place a block
            if( Math.Abs( x * 32 - pos.x ) > maxRange ||
                Math.Abs( y * 32 - pos.y ) > maxRange ||
                Math.Abs( h * 32 - pos.h ) > maxRange ) {
                SendTileNow( x, y, h );
                return false;
            }

            bool zoneOverride = false;
            string zoneName = "";
            if( world.map.CheckZones( x, y, h, this, ref zoneOverride, ref zoneName ) ) {
                if( !zoneOverride ) {
                    SendTileNow( x, y, h );
                    Message( "You are not allowed to build in \"" + zoneName + "\" zone." );
                    return false;
                }
            }

            // action block handling
            if( marksExpected > 0 ) {
                SendTileNow( x, y, h );
                marks.Push( new Position( x, y, h ) );
                markCount++;
                if( markCount >= marksExpected ) {
                    marksExpected = 0;
                    selectionCallback( this, marks.ToArray(), tag );
                } else {
                    Message( String.Format( "Block #{0} marked at ({1},{2},{3}). Place mark #{4}.",
                                            markCount, x, y, h, markCount + 1 ) );
                }
                return false;
            }

            bool can = true;
            bool update = true;
            if( type == Block.Air ) buildMode = false;

            // handle special placement modes
            switch( mode ) {
                case BlockPlacementMode.Grass:
                    if( type == Block.Dirt )
                        type = Block.Grass;
                    break;
                case BlockPlacementMode.Lava:
                    if( type == Block.Orange || type == Block.Red )
                        type = Block.StillLava;
                    break;
                case BlockPlacementMode.Solid:
                    if( type == Block.Stone )
                        type = Block.Admincrete;
                    break;
                case BlockPlacementMode.Water:
                    if( type == Block.Aqua || type == Block.Cyan || type == Block.Blue )
                        type = Block.StillWater;
                    break;
                case BlockPlacementMode.RealLava:
                    if (type == Block.Orange || type == Block.Red)
                        type = Block.Lava;
                    break;
                case BlockPlacementMode.RealWater:
                    if (type == Block.Aqua || type == Block.Cyan || type == Block.Blue)
                        type = Block.Water;
                    break;
                default:
                    update = false;
                    break;
            }

            // check if the user has the permission to BUILD the block
            if( buildMode || replaceMode ) {
                if(type == Block.StillLava ) {
                    can = Can( Permissions.PlaceLava );
                } else if(type == Block.StillWater ) {
                    can = Can( Permissions.PlaceWater );
                } else if( type == Block.Admincrete ) {
                    can = Can( Permissions.PlaceAdmincrete );
                } else if(type == Block.Lava) {
                    can = Can(Permissions.PlaceRealLava);
                } else if (type == Block.Water) {
                    can = Can(Permissions.PlaceRealWater);
                } else {
                    can = zoneOverride || Can( Permissions.Build );
                }
            } else {
                type = Block.Air;
            }

            // check that the user has permission to DELETE/REPLACE the block
            if( world.map.GetBlock( x, y, h ) == (byte)Block.Admincrete ) {
                can &= Can( Permissions.DeleteAdmincrete );
            } else if( world.map.GetBlock( x, y, h ) != (byte)Block.Air ) {
                can &= zoneOverride || Can( Permissions.Delete );
            }

            // Check to see if the player has hardened mode on or not and make changes accordingly
            if( hardenedMode == BlockPlacementMode.Hardened ) {
                Message( "This mode doesn't work yet." );
            }

            // if all is well, try placing it
            if( can ) {
                ItemEntity[] ietpl = new ItemEntity[world.map.ietlist.Count+1];
                world.map.ietlist.CopyTo(ietpl);
                BlockUpdate blockUpdate;
                if( type == Block.Stair && h > 0 && world.map.GetBlock( x, y, h - 1 ) == (byte)Block.Stair ) {
                    if (ientmode == BlockPlacementMode.ItemEnt)
                    {
                        if (!world.map.AddItemEntity(new ItemEntity(x, y, h - 1, ienttype), ientp))
                        {
                            Message("Placing ItemEntity failed!");
                        }
                    }
                    else if (ientmode == BlockPlacementMode.ItemEntRem)
                    {
                        foreach (ItemEntity pient in ietpl)
                        {
                            if (pient.x == x && pient.y == y && pient.h == h - 1)
                            {
                                world.map.ietlist.Remove(pient);
                                Message("ItemEntity removed.");
                            }
                        }
                    }
                    blockUpdate = new BlockUpdate( this, x, y, h - 1, (byte)Block.DoubleStair );
                    if( !world.FireChangedBlockEvent( ref blockUpdate ) ) {
                        SendTileNow( x, y, h );
                        return false;
                    }
                    world.map.QueueUpdate( blockUpdate );
                    session.SendNow( PacketWriter.MakeSetBlock( x, y, h - 1, (byte)Block.DoubleStair ) );
                    session.SendNow( PacketWriter.MakeSetBlock( x, y, h, (byte)Block.Air ) );
                } else {
                    if (ientmode == BlockPlacementMode.ItemEnt)
                    {
                        if (!world.map.AddItemEntity(new ItemEntity(x, y, h, ienttype), ientp))
                        {
                            Message("Placing ItemEntity failed!");
                        }
                    }
                    else if (ientmode == BlockPlacementMode.ItemEntRem)
                    {
                        foreach (ItemEntity pient in ietpl)
                        {
                            if (pient.x == x && pient.y == y && pient.h == h)
                            {
                                world.map.ietlist.Remove(pient);
                                Message("ItemEntity removed.");
                            }
                        }
                    }
                    if (type == Block.Air && world.map.GetBlock(x, y, h) == 46 && Can(Permissions.DestroyTNT))
                    {
                        world.map.tntpl.Clear();
                        world.map.TNTExplode(x, y, h);
                        world.map.PostQueueProcess();
                    }
                    blockUpdate = new BlockUpdate( this, x, y, h, (byte)type );
                    if( !world.FireChangedBlockEvent( ref blockUpdate ) ) {
                        SendTileNow( x, y, h );
                        return false;
                    }
                    world.map.QueueUpdate( blockUpdate );
                    if( update || replaceMode ) {
                        session.SendNow( PacketWriter.MakeSetBlock( x, y, h, (byte)type ) );
                    }
                }
            } else {
                Message( Color.Red, "You are not permitted to do that." );
                SendTileNow( x, y, h );
            }
            return false;
        }
Example #19
0
        // Applies pending updates and sends them to players (if applicable).
        internal void ProcessUpdates()
        {
            if (World == null)
            {
                throw new InvalidOperationException("Map must be assigned to a world to process updates.");
            }

            if (World.IsLocked)
            {
                if (World.IsPendingMapUnload)
                {
                    World.UnloadMap(true);
                }
                return;
            }

            int         packetsSent         = 0;
            bool        canFlush            = false;
            int         maxPacketsPerUpdate = Server.CalculateMaxPacketsPerUpdate(World);
            BlockUpdate update = new BlockUpdate();

            while (packetsSent < maxPacketsPerUpdate)
            {
                if (!updates.TryDequeue(out update))
                {
                    if (World.IsFlushing)
                    {
                        canFlush = true;
                    }
                    break;
                }

                HasChangedSinceSave = true;
                if (!InBounds(update.X, update.Y, update.Z))
                {
                    continue;
                }
                int blockIndex = Index(update.X, update.Y, update.Z);
                Blocks[blockIndex] = (byte)update.BlockType;

                if (!World.IsFlushing)
                {
                    Player[] players = World.Players;
                    for (int i = 0; i < players.Length; i++)
                    {
                        Player p = players[i];
                        if (p == update.Origin)
                        {
                            continue;
                        }
                        p.SendBlock(new Vector3I(update.X, update.Y, update.Z), update.BlockType);
                    }
                }
                packetsSent++;
            }

            if (drawOps.Count > 0)
            {
                lock ( drawOpLock ) {
                    if (drawOps.Count > 0)
                    {
                        packetsSent += ProcessDrawOps(maxPacketsPerUpdate - packetsSent);
                    }
                }
            }
            else if (canFlush)
            {
                World.EndFlushMapBuffer();
            }

            if (packetsSent == 0 && World.IsPendingMapUnload)
            {
                World.UnloadMap(true);
            }
        }
Example #20
0
        public static void PlayerMoving(object poo, fCraft.Events.PlayerMovingEventArgs e)
        {
            if (!started)
            {
                return;
            }
            //If the player has the red flag (player is no the blue team)
            if (e.Player.Info.hasRedFlag)
            {
                Vector3I oldPos = e.OldPosition.ToBlockCoords(); //get positions as block coords
                Vector3I newPos = e.NewPosition.ToBlockCoords();

                if (oldPos.X != newPos.X || oldPos.Y != newPos.Y || oldPos.Z != newPos.Z) //check if player has moved at least one block
                {
                    //If the player is near enough to the blue spawn
                    if (e.NewPosition.DistanceSquaredTo(world_.blueCTFSpawn.ToPlayerCoords()) <= 42 * 42)
                    {
                        blueScore++;
                        world_.Players.Message("&f{0} has capped the &cred &fflag. The score is now &cRed&f: {1} and &1Blue&f: {2}.", e.Player.Name, redScore, blueScore);
                        e.Player.Info.hasRedFlag = false;
                        redFlagHolder = null;
                        e.Player.Info.CTFCaptures++;

                        //Replace red block as flag
                        BlockUpdate blockUpdate = new BlockUpdate(null, world_.redFlag, Block.Red);
                        foreach (Player p in world_.Players)
                        {
                            p.World.Map.QueueUpdate(blockUpdate);

                            //set game score
                            if (p.ClassiCube && Heartbeat.ClassiCube())
                            {
                                p.Send(PacketWriter.MakeSpecialMessage((byte)2, "&cRed&f: " + redScore + ",&1 Blue&f: " + blueScore));
                                p.Send(PacketWriter.MakeSpecialMessage((byte)100, e.Player.Name + " has successfully capped the &cred &fflag"));
                            }
                        }
                        world_.redFlagTaken = false;
                        announced = DateTime.Now;
                        return;
                    }
                }
            }
            //If the player has the blue flag (player must be on red team)
            else if (e.Player.Info.hasBlueFlag)
            {
                Vector3I oldPos = e.OldPosition.ToBlockCoords(); //get positions as block coords
                Vector3I newPos = e.NewPosition.ToBlockCoords();

                if (oldPos.X != newPos.X || oldPos.Y != newPos.Y || oldPos.Z != newPos.Z) //check if player has moved at least one block
                {
                    //If the player is near enough to the red spawn
                    if (e.NewPosition.DistanceSquaredTo(world_.redCTFSpawn.ToPlayerCoords()) <= 42 * 42)
                    {
                        redScore++;
                        world_.Players.Message("&f{0} has capped the &1blue &fflag. The score is now &cRed&f: {1} and &1Blue&f: {2}.", e.Player.Name, redScore, blueScore);
                        e.Player.Info.hasBlueFlag = false;
                        blueFlagHolder = null;
                        e.Player.Info.CTFCaptures++;

                        //Replace blue block as flag
                        BlockUpdate blockUpdate = new BlockUpdate(null, world_.blueFlag, Block.Blue);
                        foreach (Player p in world_.Players)
                        {
                            p.World.Map.QueueUpdate(blockUpdate);

                            //set game scorecboard
                            if (p.ClassiCube && Heartbeat.ClassiCube())
                            {
                                p.Send(PacketWriter.MakeSpecialMessage((byte)2, "&cRed&f: " + redScore + ",&1 Blue&f: " + blueScore));
                                p.Send(PacketWriter.MakeSpecialMessage((byte)100, e.Player.Name + " has successfully capped the &cred &fflag"));
                            }
                        }
                        world_.blueFlagTaken = false;
                        announced = DateTime.Now;
                        return;
                    }
                }
            }

            //backstabbing, player with a flag cannot backstab an enemy player
            else
            {
                if (e.Player.Info.stabDisarmed)
                {
                    return;
                }

                Vector3I oldPos = e.OldPosition.ToBlockCoords(); //get positions as block coords
                Vector3I newPos = e.NewPosition.ToBlockCoords();

                if (oldPos.X != newPos.X || oldPos.Y != newPos.Y || oldPos.Z != newPos.Z) //check if player has moved at least one block
                {
                    //loop through each player, detect if current player is "touching" another player
                    foreach (Player p in world_.Players)
                    {
                        Vector3I pos = p.Position.ToBlockCoords(); //convert to block coords

                        //determine if player is "touching" another player
                        if (e.NewPosition.DistanceSquaredTo(pos.ToPlayerCoords()) <= 42 * 42 && p != e.Player)
                        {
                            if ((p.Info.CTFBlueTeam && e.Player.Info.CTFBlueTeam) || (p.Info.CTFRedTeam && e.Player.Info.CTFRedTeam))
                            {
                                //friendly fire, do not stab
                                return;
                            }

                            //create just under a 180 degree semicircle in the direction the target player is facing (90 degrees = 64 pos.R bytes)
                            short lowerLimit = (short)(p.Position.R - 63);
                            short upperLimit = (short)(p.Position.R + 63);

                            //if lower limit is -45 degrees for example, convert to 256 + (-32) = 201 bytes (-45 degrees translates to -32 bytes)
                            if (lowerLimit < 0)
                            {
                                lowerLimit = (short)(256 + lowerLimit);
                            }

                            //if upper limit is 450 degrees for example, convert to 320 - 256 = 54 bytes (450 degrees translates to 320 bytes, 360 degrees translates to 256 bytes)
                            if (upperLimit > 256)
                            {
                                upperLimit = (short)(upperLimit - 256);
                            }

                            //Logger.LogToConsole(upperLimit.ToString() + " " + lowerLimit.ToString() + " " + e.Player.Position.R.ToString() + " " + p.Position.R);

                            bool kill = false;

                            //if target's line of sight contains 0
                            if (p.Position.R > 192 && p.Position.R < 64)
                            {
                                if (Enumerable.Range(lowerLimit, 255).Contains(e.Player.Position.R) || Enumerable.Range(0, upperLimit).Contains(e.Player.Position.R))
                                {
                                    kill = true;
                                }
                            }
                            else
                            {
                                if (Enumerable.Range(lowerLimit, upperLimit).Contains(e.Player.Position.R))
                                {
                                    kill = true;
                                }
                            }

                            if (e.Player.Info.stabAnywhere)
                            {
                                kill = true;
                            }

                            if (kill)
                            {
                                p.KillCTF(world_, String.Format("&f{0}&S was backstabbed by &f{1}", p.Name, e.Player.Name));
                                e.Player.Info.CTFKills++;
                                PowerUp(e.Player);

                                if (p.Info.hasRedFlag)
                                {
                                    world_.Players.Message("The red flag has been returned.");
                                    p.Info.hasRedFlag = false;
                                    redFlagHolder = null;

                                    //Put flag back
                                    BlockUpdate blockUpdate = new BlockUpdate(null, world_.redFlag, Block.Red);
                                    foreach (Player pl in world_.Players)
                                    {
                                        pl.World.Map.QueueUpdate(blockUpdate);
                                    }
                                    world_.redFlagTaken = false;

                                }

                                if (p.Info.hasBlueFlag)
                                {
                                    world_.Players.Message("The blue flag has been returned.");
                                    p.Info.hasBlueFlag = false;
                                    blueFlagHolder = null;

                                    //Put flag back
                                    BlockUpdate blockUpdate = new BlockUpdate(null, world_.blueFlag, Block.Blue);
                                    foreach (Player pl in world_.Players)
                                    {
                                        pl.World.Map.QueueUpdate(blockUpdate);
                                    }
                                    world_.blueFlagTaken = false;
                                }
                            }
                            //target player can see player, do not stab
                        }
                    }
                }
            }
        }
Example #21
0
        //hitted? jonty I thought you were better than that :(
        public void HitPlayer(World world, Vector3I pos, Player hitted, Player by, ref int restDistance, IList <BlockUpdate> updates)
        {
            //Capture the flag
            if (by.Info.isPlayingCTF)
            {
                //Friendly fire
                if ((hitted.Info.CTFBlueTeam && by.Info.CTFBlueTeam) || (hitted.Info.CTFRedTeam && by.Info.CTFRedTeam))
                {
                    by.Message("{0} is on your team!", hitted.Name);
                    return;
                }

                if (hitted.Info.canDodge)
                {
                    int dodgeChance = (new Random()).Next(0, 2);
                    if (dodgeChance == 0)
                    {
                        by.Message("{0} dodged your attack!", hitted.Name);
                        return;
                    }
                }
                //Take the hit, one in ten chance of a critical hit which does 50 damage instead of 25
                int critical = (new Random()).Next(0, 9);

                if (critical == 0)
                {
                    if (by.Info.strengthened)                   //critical by a strengthened enemy instantly kills
                    {
                        hitted.Info.Health = 0;
                    }
                    else
                    {
                        hitted.Info.Health -= 50;
                    }
                    world.Players.Message("{0} landed a critical shot on {1}!", by.Name, hitted.Name);
                }
                else
                {
                    if (by.Info.strengthened)
                    {
                        hitted.Info.Health -= 50;
                    }
                    else
                    {
                        hitted.Info.Health -= 25;
                    }
                }

                //Create epic ASCII Health Bar

                string healthBar = "&f[&a--------&f]";
                if (hitted.Info.Health == 75)
                {
                    healthBar = "&f[&a------&8--&f]";
                }
                else if (hitted.Info.Health == 50)
                {
                    healthBar = "&f[&e----&8----&f]";
                }
                else if (hitted.Info.Health == 25)
                {
                    healthBar = "&f[&c--&8------&f]";
                }
                else if (hitted.Info.Health <= 0)
                {
                    healthBar = "&f[&8--------&f]";
                }

                if (hitted.usesCPE)
                {
                    hitted.Send(PacketWriter.MakeSpecialMessage((byte)1, healthBar));
                }
                else
                {
                    hitted.Message("You have " + hitted.Info.Health.ToString() + " health.");
                }

                //If the hit player's health is 0 or less, they die
                if (hitted.Info.Health <= 0)
                {
                    hitted.KillCTF(world, String.Format("&f{0}&S was shot by &f{1}", hitted.Name, by.Name));
                    CTF.PowerUp(by);
                    hitted.Info.CTFKills++;

                    if (hitted.Info.hasRedFlag)
                    {
                        world.Players.Message("The red flag has been returned.");
                        hitted.Info.hasRedFlag = false;

                        //Put flag back
                        BlockUpdate blockUpdate = new BlockUpdate(null, world.redFlag, Block.Red);
                        foreach (Player p in world.Players)
                        {
                            p.World.Map.QueueUpdate(blockUpdate);
                        }
                        world.redFlagTaken = false;
                    }

                    if (hitted.Info.hasBlueFlag)
                    {
                        world.Players.Message("The blue flag has been returned.");
                        hitted.Info.hasBlueFlag = false;

                        //Put flag back
                        BlockUpdate blockUpdate = new BlockUpdate(null, world.blueFlag, Block.Blue);
                        foreach (Player p in world.Players)
                        {
                            p.World.Map.QueueUpdate(blockUpdate);
                        }
                        world.blueFlagTaken = false;
                    }

                    //revive dead players with 100% health
                    hitted.Info.Health = 100;

                    if (hitted.usesCPE)
                    {
                        hitted.Send(PacketWriter.MakeSpecialMessage((byte)1, "&f[&a--------&f]"));
                    }
                    else
                    {
                        hitted.Message("You have 100 health.");
                    }
                }

                return;
            }

            //TDM and FFA
            if ((hitted.Info.isOnBlueTeam && by.Info.isOnBlueTeam) || (hitted.Info.isOnRedTeam && by.Info.isOnRedTeam))
            {
                by.Message("{0} is on your team!", hitted.ClassyName);
            }
            else
            {
                //Take the hit, one in ten chance of a critical hit which does 50 damage instead of 25
                int critical = (new Random()).Next(0, 9);

                if (critical == 0)
                {
                    hitted.Info.Health -= 50;
                    world.Players.Message("{0} landed a critical shot on {1}!", by.Name, hitted.Name);
                }
                else
                {
                    hitted.Info.Health -= 25;
                }

                if (hitted.Info.Health < 0)
                {
                    hitted.Info.Health = 0;
                }

                //Create epic ASCII Health Bar

                string healthBar = "&f[&a--------&f]";
                if (hitted.Info.Health == 75)
                {
                    healthBar = "&f[&a------&8--&f]";
                }
                else if (hitted.Info.Health == 50)
                {
                    healthBar = "&f[&e----&8----&f]";
                }
                else if (hitted.Info.Health == 25)
                {
                    healthBar = "&f[&c--&8------&f]";
                }
                else
                {
                    healthBar = "&f[&8--------&f]";
                }
                hitted.Send(PacketWriter.MakeSpecialMessage((byte)1, healthBar));
                if (hitted.usesCPE)
                {
                    hitted.Send(PacketWriter.MakeSpecialMessage((byte)1, healthBar));
                }
                else
                {
                    hitted.Message("You have " + hitted.Info.Health.ToString() + " health.");
                }

                if (hitted.Info.Health == 0)
                {
                    hitted.Kill(world, String.Format("{0}&S was shot by {1}", hitted.ClassyName, hitted.ClassyName == by.ClassyName ? "theirself" : by.ClassyName));
                    updates.Add(new BlockUpdate(null, pos, Block.Air));
                    restDistance = 0;

                    //TDM
                    if (fCraft.TeamDeathMatch.isOn)
                    {
                        if (hitted.Info.isPlayingTD && hitted.Info.isOnBlueTeam && by.Info.isPlayingTD)                        //if the player is playing TD and on blue team, +1 for Red Team Score
                        {
                            fCraft.TeamDeathMatch.redScore++;
                            hitted.Info.gameDeaths++;
                            hitted.Info.totalDeathsTDM++;
                            by.Info.gameKills++;
                            by.Info.totalKillsTDM++;
                        }
                        if (hitted.Info.isPlayingTD && hitted.Info.isOnRedTeam && by.Info.isPlayingTD)                        //if the player is playing TD and on blue team, +1 for Red Team Score
                        {
                            fCraft.TeamDeathMatch.blueScore++;
                            hitted.Info.gameDeaths++;                                   //counts the individual players deaths
                            hitted.Info.totalDeathsTDM++;                               //tallies total TDM deaths(never gets reset)
                            by.Info.gameKills++;                                        //counts the individual players amount of kills
                            by.Info.totalKillsTDM++;                                    //tallies total TDM kills
                        }

                        //update scoreboard for all players
                        foreach (Player p in hitted.World.Players)
                        {
                            if (p.usesCPE)
                            {
                                p.Send(PacketWriter.MakeSpecialMessage((byte)2, "&cRed&f: " + fCraft.TeamDeathMatch.redScore + ",&1 Blue&f: " + fCraft.TeamDeathMatch.blueScore));
                            }
                            else
                            {
                                p.Message("The score is now &cRed&f: " + fCraft.TeamDeathMatch.redScore + ",&1 Blue&f: " + fCraft.TeamDeathMatch.blueScore);
                            }
                        }
                    }

                    //FFA
                    if (FFA.isOn())
                    {
                        if (hitted.Info.isPlayingFFA && by.Info.isPlayingFFA)                        //if the player is playing FFA and the person they hit is also playing
                        {
                            hitted.Info.gameDeathsFFA++;
                            hitted.Info.totalDeathsFFA++;
                            by.Info.gameKillsFFA++;
                            by.Info.totalKillsFFA++;
                        }

                        //find current kill leader
                        Player leader = new Player("");                        //create a temp pseudo player
                        int    kills  = 0;

                        foreach (Player p in hitted.World.Players)
                        {
                            if (p.Info.gameKillsFFA > kills)
                            {
                                kills  = p.Info.gameKillsFFA;
                                leader = p;
                            }
                        }
                        foreach (Player p in hitted.World.Players)
                        {
                            if (p.usesCPE)
                            {
                                p.Send(PacketWriter.MakeSpecialMessage((byte)2, "&eCurrent Leader&f: " + leader.Name + ", Kills: " + leader.Info.gameKillsFFA));
                            }
                        }
                    }

                    //revive dead players with 100% health
                    hitted.Info.Health = 100;

                    if (hitted.usesCPE)
                    {
                        hitted.Send(PacketWriter.MakeSpecialMessage((byte)1, "&f[&a--------&f]"));
                    }
                    else
                    {
                        hitted.Message("You have " + hitted.Info.Health.ToString() + "health.");
                    }
                }
            }
        }
Example #22
0
        static void MessageBlockAdd( Player player, Vector3I[] marks, object tag )
        {
            string Message = ( string )tag;
            Vector3I mark = marks[0];
            if ( !player.Info.Rank.AllowSecurityCircumvention ) {
                SecurityCheckResult buildCheck = player.World.BuildSecurity.CheckDetailed( player.Info );
                switch ( buildCheck ) {
                    case SecurityCheckResult.BlackListed:
                        player.Message( "Cannot add a MessageBlock to world {0}&S: You are barred from building here.",
                                        player.World.ClassyName );
                        return;
                    case SecurityCheckResult.RankTooLow:
                        player.Message( "Cannot add a MessageBlock to world {0}&S: You are not allowed to build here.",
                                        player.World.ClassyName );
                        return;
                    //case SecurityCheckResult.RankTooHigh:
                }
            }
            if ( player.LastUsedBlockType != Block.Undefined ) {
                Vector3I Pos = mark;

                if ( player.CanPlace( player.World.Map, Pos, player.LastUsedBlockType, BlockChangeContext.Manual ) != CanPlaceResult.Allowed ) {
                    player.Message( "&WYou are not allowed to build here" );
                    return;
                }

                Player.RaisePlayerPlacedBlockEvent( player, player.WorldMap, Pos, player.WorldMap.GetBlock( Pos ), player.LastUsedBlockType, BlockChangeContext.Manual );
                BlockUpdate blockUpdate = new BlockUpdate( null, Pos, player.LastUsedBlockType );
                player.World.Map.QueueUpdate( blockUpdate );
            } else {
                player.Message( "&WError: No last used blocktype was found" );
                return;
            }
            MessageBlock MessageBlock = new MessageBlock( player.World.Name, mark,
                MessageBlock.GenerateName( player.World ),
                player.ClassyName, Message );
            MessageBlock.Range = new MessageBlockRange( mark.X, mark.X, mark.Y, mark.Y, mark.Z, mark.Z );

            MessageBlockHandler.CreateMessageBlock( MessageBlock, player.World );
            NormalBrush brush = new NormalBrush( Block.Air );
            Logger.Log( LogType.UserActivity, "{0} created MessageBlock {1} (on world {2})", player.Name, MessageBlock.Name, player.World.Name );
            player.Message( "MessageBlock created on world {0}&S with name {1}", player.World.ClassyName, MessageBlock.Name );
        }
Example #23
0
        protected override int PerformInternal()
        {
            //lock is done already
            if (Block.Undefined == _prevBlock) //created out of bounds, dont continue
                return 0;
            //fix for portal gun
            if (_owner.orangePortal.Count > 0){
                if (_pos == _owner.orangePortal[0] || _pos == _owner.orangePortal[1])
                    return 0;
            }if (_owner.bluePortal.Count > 0){
                if (_pos == _owner.bluePortal[0] || _pos == _owner.bluePortal[1])
                    return 0;
            }

            //delete at the previous position, restore water unconditionally, lava only when bullet is still there to prevent restoration of explosion lava
            if (_prevBlock != Block.Water)
                _prevBlock = _map.GetBlock(_pos) == _block ? //is the bullet still here
                    (_prevBlock == Block.Lava ? Block.Lava : Block.Air)  //yes, then either restore lava or set air
                    : Block.Undefined; //no, it was removed by some other process, do nothing then

            if (Block.Undefined != _prevBlock)
                UpdateMap(new BlockUpdate(null, _pos, _prevBlock));

            List<BlockUpdate> updates = new List<BlockUpdate>();
            for (int i = 0; i < _behavior.MovesPerProcessingStep && _restDistance > 0; ++i)
            {
                _pos = Move();
                _prevBlock = _map.GetBlock(_pos);

                if (Block.Undefined == _prevBlock)
                {
                    _restDistance = 0;
                    break;
                }

                _behavior.ModifyDirection(ref _direction, _prevBlock); //e.g. if you want it to be dependent on gravity or change direction depending on current block etc

                if (_behavior.VisitBlock(_world, _pos, _prevBlock, _owner, ref _restDistance, updates, _block) && _behavior.CanKillPlayer)
                    CheckHitPlayers(updates);
            }

            bool cont = _restDistance > 0;
            if (cont) //check if the last update was for the current position and replace it with the particle
            {
                int idx = updates.Count - 1;
                if (idx >= 0 && updates[idx].X == _pos.X
                    && updates[idx].Y == _pos.Y
                    && updates[idx].Z == _pos.Z)
                {
                    updates[idx] = new BlockUpdate(null, _pos, _block);
                }
                else
                    updates.Add(new BlockUpdate(null, _pos, _block));
            }

            for (int i = 0; i < updates.Count; ++i)
                UpdateMap(updates[i]);

            return cont ? _stepDelay : 0;
        }
        static void Place(Player player, Command cmd)
        {
            if (player.LastUsedBlockType != Block.Undefined)
            {
                Vector3I Pos = new Vector3I(player.Position.X / 32, player.Position.Y / 32, (player.Position.Z / 32) - 2);

                if (player.CanPlace(player.World.Map, Pos, player.LastUsedBlockType, BlockChangeContext.Manual) != CanPlaceResult.Allowed)
                {
                    player.Message("&WYou are not allowed to build here");
                    return;
                }

                Player.RaisePlayerPlacedBlockEvent(player, player.WorldMap, Pos, player.WorldMap.GetBlock(Pos), player.LastUsedBlockType, BlockChangeContext.Manual);
                BlockUpdate blockUpdate = new BlockUpdate(null, Pos, player.LastUsedBlockType);
                player.World.Map.QueueUpdate(blockUpdate);
                player.Message("Block placed below your feet");
            }
            else player.Message("&WError: No last used blocktype was found");
        }
Example #25
0
        /// <summary> Handles manually-placed/deleted blocks.
        /// Returns true if player's action should result in a kick. </summary>
        public bool PlaceBlock( short x, short y, short h, bool buildMode, Block type ) {

            LastUsedBlockType = type;

            // check if player is frozen or too far away to legitimately place a block
            if( Info.IsFrozen ||
                Math.Abs( x * 32 - Position.X ) > MaxRange ||
                Math.Abs( y * 32 - Position.Y ) > MaxRange ||
                Math.Abs( h * 32 - Position.H ) > MaxRange ) {
                RevertBlockNow( x, y, h );
                return false;
            }

            if( World.IsLocked ) {
                RevertBlockNow( x, y, h );
                Message( "This map is currently locked (read-only)." );
                return false;
            }

            if( CheckBlockSpam() ) return true;

            // bindings
            bool requiresUpdate = (type != bindings[(byte)type] || IsPainting);
            if( !buildMode && !IsPainting ) {
                type = Block.Air;
            }
            type = bindings[(byte)type];

            // selection handling
            if( SelectionMarksExpected > 0 ) {
                RevertBlockNow( x, y, h );
                AddSelectionMark( new Position( x, y, h ), true );
                return false;
            }

            CanPlaceResult canPlaceResult;
            if( type == Block.Stair && h > 0 && World.Map.GetBlock( x, y, h - 1 ) == Block.Stair ) {
                // stair stacking
                canPlaceResult = CanPlace( x, y, h - 1, Block.DoubleStair, true );
            } else {
                // normal placement
                canPlaceResult = CanPlace( x, y, h, type, true );
            }

            // if all is well, try placing it
            switch( canPlaceResult ) {
                case CanPlaceResult.Allowed:
                    BlockUpdate blockUpdate;
                    if( type == Block.Stair && h > 0 && World.Map.GetBlock( x, y, h - 1 ) == Block.Stair ) {
                        // handle stair stacking
                        blockUpdate = new BlockUpdate( this, x, y, h - 1, Block.DoubleStair );
                        if( !World.FireChangedBlockEvent( ref blockUpdate ) ) {
                            RevertBlockNow( x, y, h );
                            return false;
                        }
                        Info.ProcessBlockPlaced( (byte)Block.DoubleStair );
                        World.Map.QueueUpdate( blockUpdate );
                        Server.RaisePlayerPlacedBlockEvent( this, x, y, (short)(h - 1), Block.Stair, Block.DoubleStair, true );
                        Session.SendNow( PacketWriter.MakeSetBlock( x, y, h - 1, Block.DoubleStair ) );
                        RevertBlockNow( x, y, h );
                        break;

                    } else {
                        // handle normal blocks
                        blockUpdate = new BlockUpdate( this, x, y, h, type );
                        if( !World.FireChangedBlockEvent( ref blockUpdate ) ) {
                            RevertBlockNow( x, y, h );
                            return false;
                        }
                        Info.ProcessBlockPlaced( (byte)type );
                        Block old = World.Map.GetBlock(x, y, h);
                        World.Map.QueueUpdate( blockUpdate );
                        Server.RaisePlayerPlacedBlockEvent( this, x, y, h, old, type, true );
                        if( requiresUpdate || RelayAllUpdates ) {
                            Session.SendNow( PacketWriter.MakeSetBlock( x, y, h, type ) );
                        }
                    }
                    break;

                case CanPlaceResult.BlocktypeDenied:
                    Message( "&WYou are not permitted to affect this block type." );
                    RevertBlockNow( x, y, h );
                    break;

                case CanPlaceResult.RankDenied:
                    Message( "&WYour rank is not allowed to build." );
                    RevertBlockNow( x, y, h );
                    break;

                case CanPlaceResult.WorldDenied:
                    switch( World.BuildSecurity.CheckDetailed( Info ) ) {
                        case SecurityCheckResult.RankTooLow:
                        case SecurityCheckResult.RankTooHigh:
                            Message( "&WYour rank is not allowed to build in this world." );
                            break;
                        case SecurityCheckResult.BlackListed:
                            Message( "&WYou are not allowed to build in this world." );
                            break;
                    }
                    RevertBlockNow( x, y, h );
                    break;

                case CanPlaceResult.ZoneDenied:
                    Zone deniedZone = World.Map.FindDeniedZone( x, y, h, this );
                    if( deniedZone != null ) {
                        Message( "&WYou are not allowed to build in zone \"{0}\".", deniedZone.Name );
                    } else {
                        Message( "&WYou are not allowed to build here." );
                    }
                    RevertBlockNow( x, y, h );
                    break;

                case CanPlaceResult.PluginDenied:
                    RevertBlockNow( x, y, h );
                    break;

                //case CanPlaceResult.PluginDeniedNoUpdate:
                //    break;
            }
            return false;
        }
Example #26
0
        /// <summary> Handles manually-placed/deleted blocks.
        /// Returns true if player's action should result in a kick. </summary>
        public bool PlaceBlock(short x, short y, short h, bool buildMode, Block type)
        {
            LastUsedBlockType = type;

            // check if player is frozen or too far away to legitimately place a block
            if (Info.IsFrozen ||
                Math.Abs(x * 32 - Position.X) > MaxRange ||
                Math.Abs(y * 32 - Position.Y) > MaxRange ||
                Math.Abs(h * 32 - Position.H) > MaxRange)
            {
                RevertBlockNow(x, y, h);
                return(false);
            }

            if (World.IsLocked)
            {
                RevertBlockNow(x, y, h);
                Message("This map is currently locked (read-only).");
                return(false);
            }

            if (CheckBlockSpam())
            {
                return(true);
            }

            // bindings
            bool requiresUpdate = (type != bindings[(byte)type] || IsPainting);

            if (!buildMode && !IsPainting)
            {
                type = Block.Air;
            }
            type = bindings[(byte)type];

            // selection handling
            if (SelectionMarksExpected > 0)
            {
                RevertBlockNow(x, y, h);
                AddSelectionMark(new Position(x, y, h), true);
                return(false);
            }

            CanPlaceResult canPlaceResult;

            if (type == Block.Stair && h > 0 && World.Map.GetBlock(x, y, h - 1) == Block.Stair)
            {
                // stair stacking
                canPlaceResult = CanPlace(x, y, h - 1, Block.DoubleStair, true);
            }
            else
            {
                // normal placement
                canPlaceResult = CanPlace(x, y, h, type, true);
            }

            // if all is well, try placing it
            switch (canPlaceResult)
            {
            case CanPlaceResult.Allowed:
                BlockUpdate blockUpdate;
                if (type == Block.Stair && h > 0 && World.Map.GetBlock(x, y, h - 1) == Block.Stair)
                {
                    // handle stair stacking
                    blockUpdate = new BlockUpdate(this, x, y, h - 1, Block.DoubleStair);
                    if (!World.FireChangedBlockEvent(ref blockUpdate))
                    {
                        RevertBlockNow(x, y, h);
                        return(false);
                    }
                    Info.ProcessBlockPlaced((byte)Block.DoubleStair);
                    World.Map.QueueUpdate(blockUpdate);
                    Server.RaisePlayerPlacedBlockEvent(this, x, y, (short)(h - 1), Block.Stair, Block.DoubleStair, true);
                    Session.SendNow(PacketWriter.MakeSetBlock(x, y, h - 1, Block.DoubleStair));
                    RevertBlockNow(x, y, h);
                    break;
                }
                else
                {
                    // handle normal blocks
                    blockUpdate = new BlockUpdate(this, x, y, h, type);
                    if (!World.FireChangedBlockEvent(ref blockUpdate))
                    {
                        RevertBlockNow(x, y, h);
                        return(false);
                    }
                    Info.ProcessBlockPlaced((byte)type);
                    Block old = World.Map.GetBlock(x, y, h);
                    World.Map.QueueUpdate(blockUpdate);
                    Server.RaisePlayerPlacedBlockEvent(this, x, y, h, old, type, true);
                    if (requiresUpdate || RelayAllUpdates)
                    {
                        Session.SendNow(PacketWriter.MakeSetBlock(x, y, h, type));
                    }
                }
                break;

            case CanPlaceResult.BlocktypeDenied:
                Message("&WYou are not permitted to affect this block type.");
                RevertBlockNow(x, y, h);
                break;

            case CanPlaceResult.RankDenied:
                Message("&WYour rank is not allowed to build.");
                RevertBlockNow(x, y, h);
                break;

            case CanPlaceResult.WorldDenied:
                switch (World.BuildSecurity.CheckDetailed(Info))
                {
                case SecurityCheckResult.RankTooLow:
                case SecurityCheckResult.RankTooHigh:
                    Message("&WYour rank is not allowed to build in this world.");
                    break;

                case SecurityCheckResult.BlackListed:
                    Message("&WYou are not allowed to build in this world.");
                    break;
                }
                RevertBlockNow(x, y, h);
                break;

            case CanPlaceResult.ZoneDenied:
                Zone deniedZone = World.Map.FindDeniedZone(x, y, h, this);
                if (deniedZone != null)
                {
                    Message("&WYou are not allowed to build in zone \"{0}\".", deniedZone.Name);
                }
                else
                {
                    Message("&WYou are not allowed to build here.");
                }
                RevertBlockNow(x, y, h);
                break;

            case CanPlaceResult.PluginDenied:
                RevertBlockNow(x, y, h);
                break;

                //case CanPlaceResult.PluginDeniedNoUpdate:
                //    break;
            }
            return(false);
        }
Example #27
0
 protected void UpdateMap(BlockUpdate upd)
 {
     _map.SetBlock(upd.X, upd.Y, upd.Z, upd.BlockType);
     _map.QueueUpdate(upd);
 }
Example #28
0
        // Applies pending updates and sends them to players (if applicable).
        internal void ProcessUpdates()
        {
            if( World == null ) {
                throw new InvalidOperationException( "Map must be assigned to a world to process updates." );
            }

            if( World.IsLocked ) {
                if( World.IsPendingMapUnload ) {
                    World.UnloadMap( true );
                }
                return;
            }

            int packetsSent = 0;
            bool canFlush = false;
            int maxPacketsPerUpdate = Server.CalculateMaxPacketsPerUpdate( World );
            BlockUpdate update = new BlockUpdate();
            while( packetsSent < maxPacketsPerUpdate ) {
                if( !updates.Dequeue( ref update ) ) {
                    if( World.IsFlushing ) {
                        canFlush = true;
                    }
                    break;
                }
                HasChangedSinceSave = true;
                if( !InBounds( update.X, update.Y, update.Z ) ) continue;
                int blockIndex = Index( update.X, update.Y, update.Z );
                Blocks[blockIndex] = (byte)update.BlockType;

                if( !World.IsFlushing ) {
                    Packet packet = PacketWriter.MakeSetBlock( update.X, update.Y, update.Z, update.BlockType );
                    World.Players.SendLowPriority( update.Origin, packet );
                }
                packetsSent++;
            }

            if( drawOps.Count > 0 ) {
                lock( drawOpLock ) {
                    if( drawOps.Count > 0 ) {
                        packetsSent += ProcessDrawOps( maxPacketsPerUpdate - packetsSent );
                    }
                }
            } else if( canFlush ) {
                World.EndFlushMapBuffer();
            }

            if( packetsSent == 0 && World.IsPendingMapUnload ) {
                World.UnloadMap( true );
            }
        }
Example #29
0
 /// <summary> Queues a new block update to be processed.
 /// Due to concurrent nature of the server, there is no guarantee
 /// that updates will be applied in any specific order. </summary>
 public void QueueUpdate(BlockUpdate update)
 {
     updates.Enqueue(update);
 }
Example #30
0
        static void textureHandler(Player player, CommandReader cmd)
        {            
            Zone zone = player.World.Map.Zones.Find("ctest");
            int X = zone.Bounds.XMin;
            int Y = zone.Bounds.YMin;
            int Z = zone.Bounds.ZMin;

            for (int a = 0; a < zone.Bounds.Width; a++)
            {
                player.WorldMap.SetBlock(X + a, Y, Z, Block.Stone);
                BlockUpdate blockUpdatea = new BlockUpdate(null, new Vector3I(X + a, Y, Z), Block.Stone);
                player.WorldMap.QueueUpdate(blockUpdatea);
                for (int b = 0; b < zone.Bounds.Length; b++)
                {
                    player.WorldMap.SetBlock(X + a, Y + b, Z, Block.Stone);
                    BlockUpdate blockUpdateb = new BlockUpdate(null, new Vector3I(X + a, Y + b, Z), Block.Stone);
                    player.WorldMap.QueueUpdate(blockUpdateb);
                    for (int c = 0; c < zone.Bounds.Height; c++)
                    {
                        player.WorldMap.SetBlock(X + a, Y + b, Z + c, Block.Stone);
                        BlockUpdate blockUpdatec = new BlockUpdate(null, new Vector3I(X + a, Y + b, Z + c), Block.Stone);
                        player.WorldMap.QueueUpdate(blockUpdatec);
                    }
                }
            }
            player.Message("Done.");
            return;
        }
Example #31
0
        //I left this class rather generic incase i used it for anything else
        /// <summary>
        /// Updates a specific block for a given time
        /// </summary>
        private void updateBlock(Block blockType, Vector3I blockPosition, bool replaceWithAir, double time)
        {
            BlockUpdate update = new BlockUpdate(null, blockPosition, blockType);
            foreach (Player p in World.Players)
            {
                p.World.Map.QueueUpdate(update);
            }

            if (replaceWithAir)
            {
                Scheduler.NewTask(t => updateBlock(Block.Air, blockPosition, false, time)).RunManual(TimeSpan.FromSeconds(time));//place a block, replace it with air once 'time' is up
            }
        }
Example #32
0
        internal static void Undo( Player player, Command command ) {
            if( player.UndoBuffer.Count > 0 ) {
                // no need to set player.drawingInProgress here because this is done on the user thread
                Logger.Log( "Player {0} initiated /undo affecting {1} blocks (on world {2})", LogType.UserActivity,
                            player.Name,
                            player.UndoBuffer.Count,
                            player.World.Name );
                player.MessageNow( "Restoring {0} blocks...", player.UndoBuffer.Count );
                Queue<BlockUpdate> redoBuffer = new Queue<BlockUpdate>();
                while( player.UndoBuffer.Count > 0 ) {
                    BlockUpdate newBlock = player.UndoBuffer.Dequeue();
                    BlockUpdate oldBlock = new BlockUpdate( null, newBlock.X, newBlock.Y, newBlock.H,
                                                            player.World.Map.GetBlock( newBlock.X, newBlock.Y, newBlock.H ) );
                    player.World.Map.QueueUpdate( newBlock );
                    redoBuffer.Enqueue( oldBlock );
                }
                player.UndoBuffer = redoBuffer;
                redoBuffer.TrimExcess();
                player.MessageNow( "Type /undo again to reverse this command." );
                Server.RequestGC();

            } else {
                player.MessageNow( "There is currently nothing to undo." );
            }
        }
Example #33
0
 /// <summary> Queues a new block update to be processed.
 /// Due to concurrent nature of the server, there is no guarantee
 /// that updates will be applied in any specific order. </summary>
 public void QueueUpdate(BlockUpdate update) {
     updates.Enqueue(update);
 }
Example #34
0
        public static void PlayerMoving(object poo, fCraft.Events.PlayerMovingEventArgs e)
        {
            if (!started)
            {
                return;
            }
            //If the player has the red flag (player is no the blue team)
            if (e.Player.Info.hasRedFlag)
            {
                Vector3I oldPos = e.OldPosition.ToBlockCoords(); //get positions as block coords
                Vector3I newPos = e.NewPosition.ToBlockCoords();

                if (oldPos.X != newPos.X || oldPos.Y != newPos.Y || oldPos.Z != newPos.Z) //check if player has moved at least one block
                {
                    //If the player is near enough to the blue spawn
                    if (e.NewPosition.DistanceSquaredTo(world_.blueCTFSpawn.ToPlayerCoords()) <= 42 * 42)
                    {
                        blueScore++;
                        world_.Players.Message("&f{0} has capped the &cred &fflag. The score is now &cRed&f: {1} and &1Blue&f: {2}.", e.Player.Name, redScore, blueScore);
                        e.Player.Info.hasRedFlag = false;
                        redFlagHolder            = null;
                        e.Player.Info.CTFCaptures++;

                        //Replace red block as flag
                        BlockUpdate blockUpdate = new BlockUpdate(null, world_.redFlag, Block.Red);
                        foreach (Player p in world_.Players)
                        {
                            p.World.Map.QueueUpdate(blockUpdate);

                            //set game score
                            if (p.ClassiCube && Heartbeat.ClassiCube())
                            {
                                p.Send(PacketWriter.MakeSpecialMessage((byte)2, "&cRed&f: " + redScore + ",&1 Blue&f: " + blueScore));
                                p.Send(PacketWriter.MakeSpecialMessage((byte)100, e.Player.Name + " has successfully capped the &cred &fflag"));
                            }
                        }
                        world_.redFlagTaken = false;
                        announced           = DateTime.Now;
                        return;
                    }
                }
            }
            //If the player has the blue flag (player must be on red team)
            else if (e.Player.Info.hasBlueFlag)
            {
                Vector3I oldPos = e.OldPosition.ToBlockCoords(); //get positions as block coords
                Vector3I newPos = e.NewPosition.ToBlockCoords();

                if (oldPos.X != newPos.X || oldPos.Y != newPos.Y || oldPos.Z != newPos.Z) //check if player has moved at least one block
                {
                    //If the player is near enough to the red spawn
                    if (e.NewPosition.DistanceSquaredTo(world_.redCTFSpawn.ToPlayerCoords()) <= 42 * 42)
                    {
                        redScore++;
                        world_.Players.Message("&f{0} has capped the &1blue &fflag. The score is now &cRed&f: {1} and &1Blue&f: {2}.", e.Player.Name, redScore, blueScore);
                        e.Player.Info.hasBlueFlag = false;
                        blueFlagHolder            = null;
                        e.Player.Info.CTFCaptures++;

                        //Replace blue block as flag
                        BlockUpdate blockUpdate = new BlockUpdate(null, world_.blueFlag, Block.Blue);
                        foreach (Player p in world_.Players)
                        {
                            p.World.Map.QueueUpdate(blockUpdate);

                            //set game scorecboard
                            if (p.ClassiCube && Heartbeat.ClassiCube())
                            {
                                p.Send(PacketWriter.MakeSpecialMessage((byte)2, "&cRed&f: " + redScore + ",&1 Blue&f: " + blueScore));
                                p.Send(PacketWriter.MakeSpecialMessage((byte)100, e.Player.Name + " has successfully capped the &cred &fflag"));
                            }
                        }
                        world_.blueFlagTaken = false;
                        announced            = DateTime.Now;
                        return;
                    }
                }
            }

            //backstabbing, player with a flag cannot backstab an enemy player
            else
            {
                if (e.Player.Info.stabDisarmed)
                {
                    return;
                }

                Vector3I oldPos = e.OldPosition.ToBlockCoords(); //get positions as block coords
                Vector3I newPos = e.NewPosition.ToBlockCoords();

                if (oldPos.X != newPos.X || oldPos.Y != newPos.Y || oldPos.Z != newPos.Z) //check if player has moved at least one block
                {
                    //loop through each player, detect if current player is "touching" another player
                    foreach (Player p in world_.Players)
                    {
                        Vector3I pos = p.Position.ToBlockCoords(); //convert to block coords

                        //determine if player is "touching" another player
                        if (e.NewPosition.DistanceSquaredTo(pos.ToPlayerCoords()) <= 42 * 42 && p != e.Player)
                        {
                            if ((p.Info.CTFBlueTeam && e.Player.Info.CTFBlueTeam) || (p.Info.CTFRedTeam && e.Player.Info.CTFRedTeam))
                            {
                                //friendly fire, do not stab
                                return;
                            }

                            //create just under a 180 degree semicircle in the direction the target player is facing (90 degrees = 64 pos.R bytes)
                            short lowerLimit = (short)(p.Position.R - 63);
                            short upperLimit = (short)(p.Position.R + 63);

                            //if lower limit is -45 degrees for example, convert to 256 + (-32) = 201 bytes (-45 degrees translates to -32 bytes)
                            if (lowerLimit < 0)
                            {
                                lowerLimit = (short)(256 + lowerLimit);
                            }

                            //if upper limit is 450 degrees for example, convert to 320 - 256 = 54 bytes (450 degrees translates to 320 bytes, 360 degrees translates to 256 bytes)
                            if (upperLimit > 256)
                            {
                                upperLimit = (short)(upperLimit - 256);
                            }

                            //Logger.LogToConsole(upperLimit.ToString() + " " + lowerLimit.ToString() + " " + e.Player.Position.R.ToString() + " " + p.Position.R);

                            bool kill = false;

                            //if target's line of sight contains 0
                            if (p.Position.R > 192 && p.Position.R < 64)
                            {
                                if (Enumerable.Range(lowerLimit, 255).Contains(e.Player.Position.R) || Enumerable.Range(0, upperLimit).Contains(e.Player.Position.R))
                                {
                                    kill = true;
                                }
                            }
                            else
                            {
                                if (Enumerable.Range(lowerLimit, upperLimit).Contains(e.Player.Position.R))
                                {
                                    kill = true;
                                }
                            }

                            if (e.Player.Info.stabAnywhere)
                            {
                                kill = true;
                            }

                            if (kill)
                            {
                                p.KillCTF(world_, String.Format("&f{0}&S was backstabbed by &f{1}", p.Name, e.Player.Name));
                                e.Player.Info.CTFKills++;
                                PowerUp(e.Player);

                                if (p.Info.hasRedFlag)
                                {
                                    world_.Players.Message("The red flag has been returned.");
                                    p.Info.hasRedFlag = false;
                                    redFlagHolder     = null;

                                    //Put flag back
                                    BlockUpdate blockUpdate = new BlockUpdate(null, world_.redFlag, Block.Red);
                                    foreach (Player pl in world_.Players)
                                    {
                                        pl.World.Map.QueueUpdate(blockUpdate);
                                    }
                                    world_.redFlagTaken = false;
                                }

                                if (p.Info.hasBlueFlag)
                                {
                                    world_.Players.Message("The blue flag has been returned.");
                                    p.Info.hasBlueFlag = false;
                                    blueFlagHolder     = null;

                                    //Put flag back
                                    BlockUpdate blockUpdate = new BlockUpdate(null, world_.blueFlag, Block.Blue);
                                    foreach (Player pl in world_.Players)
                                    {
                                        pl.World.Map.QueueUpdate(blockUpdate);
                                    }
                                    world_.blueFlagTaken = false;
                                }
                            }
                            //target player can see player, do not stab
                        }
                    }
                }
            }
        }