public void ClearUpdateQueue() { BlockUpdate temp = new BlockUpdate(); while (updates.Dequeue(ref temp)) { } }
public bool FireChangedBlockEvent(ref BlockUpdate update) { bool cancel = false; if (OnPlayerChangedBlock != null) { OnPlayerChangedBlock(this, ref update, ref cancel); } return(!cancel); }
/// <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 } }
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); } }
// 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!"); } }
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); } }
// 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); } }
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); } }
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) { 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"); }
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; } } }
// 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 ); } }
// 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); } }
public bool FireChangedBlockEvent( ref BlockUpdate update ) { bool cancel = false; if ( OnPlayerChangedBlock != null ) { OnPlayerChangedBlock( this, ref update, ref cancel ); } return !cancel; }
//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."); } } } }
internal void QueueUpdate(BlockUpdate update) { lock ( queueLock ) { updates.Enqueue(update); } }
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); } } } } }
// 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; }
// 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); } }
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 } } } } }
//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."); } } } }
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 ); }
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"); }
/// <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; }
/// <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); }
protected void UpdateMap(BlockUpdate upd) { _map.SetBlock(upd.X, upd.Y, upd.Z, upd.BlockType); _map.QueueUpdate(upd); }
// 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 ); } }
/// <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); }
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; }
//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 } }
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." ); } }
/// <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); }
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 } } } } }