static private MakeSetBlock ( Vector3I coords, Block type ) : |
||
coords | Vector3I | |
type | Block | |
Résultat |
public static void GunHandler(Player player, Command cmd) { if (player.GunMode) { player.GunMode = false; try { foreach (Vector3I block in player.GunCache.Values) { player.Send(PacketWriter.MakeSetBlock(block.X, block.Y, block.Z, player.WorldMap.GetBlock(block))); Vector3I removed; player.GunCache.TryRemove(block.ToString(), out removed); } if (player.bluePortal.Count > 0) { int i = 0; foreach (Vector3I block in player.bluePortal) { if (player.WorldMap != null && player.World.IsLoaded) { player.WorldMap.QueueUpdate(new BlockUpdate(null, block, player.blueOld[i])); i++; } } player.blueOld.Clear(); player.bluePortal.Clear(); } if (player.orangePortal.Count > 0) { int i = 0; foreach (Vector3I block in player.orangePortal) { if (player.WorldMap != null && player.World.IsLoaded) { player.WorldMap.QueueUpdate(new BlockUpdate(null, block, player.orangeOld[i])); i++; } } player.orangeOld.Clear(); player.orangePortal.Clear(); } player.Message("&SGunMode deactivated"); } catch (Exception ex) { Logger.Log(LogType.SeriousError, "" + ex); } } else { if (!player.World.gunPhysics) { player.Message("&WGun physics are disabled on this world"); return; } player.GunMode = true; GunGlassTimer timer = new GunGlassTimer(player); timer.Start(); player.Message("&SGunMode activated. Fire at will!"); } }
public static void towerInit(object sender, Events.PlayerPlacedBlockEventArgs e) { World world = e.Player.World; if (e.Player.towerMode) { if (world.Map != null && world.IsLoaded) { if (e.Context == BlockChangeContext.Manual) { if (e.NewBlock == Block.Iron) { waterThread = new Thread(new ThreadStart(delegate { if (e.Player.TowerCache != null) { world.Map.QueueUpdate(new BlockUpdate(null, e.Player.towerOrigin, Block.Air)); e.Player.towerOrigin = e.Coords; foreach (Vector3I block in e.Player.TowerCache.Values) { e.Player.Send(PacketWriter.MakeSetBlock(block, Block.Air)); } e.Player.TowerCache.Clear(); } e.Player.towerOrigin = e.Coords; e.Player.TowerCache = new System.Collections.Concurrent.ConcurrentDictionary <string, Vector3I>(); for (int z = e.Coords.Z; z <= world.Map.Height; z++) { Thread.Sleep(250); if (world.Map != null && world.IsLoaded) { if (world.Map.GetBlock(e.Coords.X, e.Coords.Y, z + 1) != Block.Air || world.Map.GetBlock(e.Coords) != Block.Iron || e.Player.towerOrigin != e.Coords || !e.Player.towerMode) { break; } else { Vector3I tower = new Vector3I(e.Coords.X, e.Coords.Y, z + 1); e.Player.TowerCache.TryAdd(tower.ToString(), tower); e.Player.Send(PacketWriter.MakeSetBlock(tower, Block.Water)); } } } })); waterThread.Start(); } } } } }
public static void ClickedGlass(object sender, PlayerClickingEventArgs e) { if (e.Player.GunMode && !e.Player.Info.IsHidden && !e.Player.Info.IsFrozen) { World world = e.Player.World; Map map = e.Player.World.Map; if (e.Player.GunCache.Values.Contains(e.Coords)) { if (world.gunPhysics) { e.Player.Send(PacketWriter.MakeSetBlock(e.Coords.X, e.Coords.Y, e.Coords.Z, Block.Glass)); if (e.Block == Block.TNT && world.tntPhysics) { if (e.Player.CanFireTNT()) { double ksi = 2.0 * Math.PI * (-e.Player.Position.L) / 256.0; double r = Math.Cos(ksi); double phi = 2.0 * Math.PI * (e.Player.Position.R - 64) / 256.0; Vector3F dir = new Vector3F((float)(r * Math.Cos(phi)), (float)(r * Math.Sin(phi)), (float)(Math.Sin(ksi))); world.AddPhysicsTask( new Particle(world, e.Coords, dir, e.Player, Block.TNT, _tntBulletBehavior), 0); } } else { Block block = e.Block; if (block == Block.BlueWool) { block = Block.Water; } if (block == Block.OrangeWool) { block = Block.Lava; } double ksi = 2.0 * Math.PI * (-e.Player.Position.L) / 256.0; double r = Math.Cos(ksi); double phi = 2.0 * Math.PI * (e.Player.Position.R - 64) / 256.0; Vector3F dir = new Vector3F((float)(r * Math.Cos(phi)), (float)(r * Math.Sin(phi)), (float)(Math.Sin(ksi))); world.AddPhysicsTask(new Particle(world, e.Coords, dir, e.Player, block, _bulletBehavior), 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); } }
public void ProcessUpdates() { int packetsSent = 0; int maxPacketsPerUpdate = world.server.CalculateMaxPacketsPerUpdate(); BlockUpdate update; while (updates.Count > 0 && packetsSent < maxPacketsPerUpdate) { lock ( queueLock ) { update = updates.Dequeue(); } changesSinceSave++; changesSinceBackup++; SetBlock(update.x, update.y, update.h, update.type); world.SendToAll(PacketWriter.MakeSetBlock(update.x, update.y, update.h, update.type), update.origin, false); if (update.origin != null) { update.origin.info.ProcessBlockBuild(update.type); } packetsSent++; } if (world.loadSendingInProgress) { if (packetsSent < maxPacketsPerUpdate) { GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced); GC.WaitForPendingFinalizers(); world.SendToAll(PacketWriter.MakeMessage(Color.Red + "Map load complete."), null); world.log.Log("Load command finished succesfully.", LogType.SystemActivity); world.loadSendingInProgress = false; world.EndLockDown(); } else { if (!world.loadProgressReported && world.completedBlockUpdates / (float)world.totalBlockUpdates > 0.5f) { world.SendToAll(PacketWriter.MakeMessage(Color.Red + "Map loading: 50%"), null); world.loadProgressReported = true; } world.completedBlockUpdates += packetsSent; } } }
static void makeTower(World world, Player player, Vector3I coords) { waterThread = new Thread(new ThreadStart( delegate { if (player.TowerCache != null) { world.Map.QueueUpdate(new BlockUpdate(null, player.towerOrigin, Block.Air)); player.towerOrigin = coords; foreach (Vector3I block in player.TowerCache.Values) { player.Send(PacketWriter.MakeSetBlock(block, Block.Air)); } player.TowerCache.Clear(); } player.towerOrigin = coords; player.TowerCache = new System.Collections.Concurrent.ConcurrentDictionary <string, Vector3I>(); for (int z = coords.Z; z <= world.Map.Height; z++) { Thread.Sleep(250); if (world.Map != null && world.IsLoaded) { if (world.Map.GetBlock(coords.X, coords.Y, z + 1) != Block.Air || world.Map.GetBlock(coords) != Block.Iron || player.towerOrigin != coords || !player.towerMode) { break; } else { Vector3I tower = new Vector3I(coords.X, coords.Y, z + 1); player.TowerCache.TryAdd(tower.ToString(), tower); player.Send(PacketWriter.MakeSetBlock(tower, Block.Water)); } } } })); waterThread.Start(); }
public static void towerRemove(object sender, Events.PlayerClickingEventArgs e) { World world = e.Player.World; if (e.Action == ClickAction.Delete) { if (e.Coords == e.Player.towerOrigin) { if (e.Player.TowerCache != null) { if (e.Block == Block.Iron) { e.Player.towerOrigin = new Vector3I(); foreach (Vector3I block in e.Player.TowerCache.Values) { e.Player.Send(PacketWriter.MakeSetBlock(block, world.Map.GetBlock(block))); } e.Player.TowerCache.Clear(); } } } } }
public static void gunMove(Player player) { World world = player.World; if (null == world) { return; } try { lock (world.SyncRoot) { if (null == world.Map) { return; } if (player.IsOnline) { Position p = player.Position; double ksi = 2.0 * Math.PI * (-player.Position.L) / 256.0; double phi = 2.0 * Math.PI * (player.Position.R - 64) / 256.0; double sphi = Math.Sin(phi); double cphi = Math.Cos(phi); double sksi = Math.Sin(ksi); double cksi = Math.Cos(ksi); if (player.IsOnline) { if (player.GunCache.Values.Count > 0) { foreach (Vector3I block in player.GunCache.Values) { if (player.IsOnline) { player.Send(PacketWriter.MakeSetBlock(block.X, block.Y, block.Z, world.Map.GetBlock(block))); Vector3I removed; player.GunCache.TryRemove(block.ToString(), out removed); } } } } for (int y = -1; y < 2; ++y) { for (int z = -1; z < 2; ++z) { if (player.IsOnline) { //4 is the distance betwen the player and the glass wall Vector3I glassBlockPos = new Vector3I((int)(cphi * cksi * 4 - sphi * (0.5 + y) - cphi * sksi * (0.5 + z)), (int)(sphi * cksi * 4 + cphi * (0.5 + y) - sphi * sksi * (0.5 + z)), (int)(sksi * 4 + cksi * (0.5 + z))); glassBlockPos += p.ToBlockCoords(); if (world.Map.GetBlock(glassBlockPos) == Block.Air) { player.Send(PacketWriter.MakeSetBlock(glassBlockPos, Block.Glass)); player.GunCache.TryAdd(glassBlockPos.ToString(), glassBlockPos); } } } } } } } catch (Exception ex) { Logger.Log(LogType.SeriousError, "GunGlass: " + ex); } }
public static void GunHandler(Player player, Command cmd) { //to prevent players from doing /gun during a TDM game that arent actually playing in if (player.World.gameMode == GameMode.TeamDeathMatch && !player.Info.isPlayingTD) { player.Message("Players who are not playing Team DeathMatch can only spectate."); return; } if (player.Info.isPlayingCTF && player.Info.gunDisarmed) { player.Message("You are currently disarmed. You cannot use a gun until the disarm powerup has worn off."); return; } if (player.GunMode) { player.GunMode = false; try { foreach (Vector3I block in player.GunCache.Values) { player.Send(PacketWriter.MakeSetBlock(block.X, block.Y, block.Z, player.WorldMap.GetBlock(block))); Vector3I removed; player.GunCache.TryRemove(block.ToString(), out removed); } if (player.bluePortal.Count > 0) { int i = 0; foreach (Vector3I block in player.bluePortal) { if (player.WorldMap != null && player.World.IsLoaded) { player.WorldMap.QueueUpdate(new BlockUpdate(null, block, player.blueOld[i])); i++; } } player.blueOld.Clear(); player.bluePortal.Clear(); } if (player.orangePortal.Count > 0) { int i = 0; foreach (Vector3I block in player.orangePortal) { if (player.WorldMap != null && player.World.IsLoaded) { player.WorldMap.QueueUpdate(new BlockUpdate(null, block, player.orangeOld[i])); i++; } } player.orangeOld.Clear(); player.orangePortal.Clear(); } player.Message("&SGunMode deactivated"); } catch (Exception ex) { Logger.Log(LogType.SeriousError, "" + ex); } } else { if (!player.World.gunPhysics) { player.Message("&WGun physics are disabled on this world"); return; } player.GunMode = true; GunGlassTimer timer = new GunGlassTimer(player); timer.Start(); player.Message("&SGunMode activated. Fire at will!"); } }
public static void RevertNames() //reverts names for online players. offline players get reverted upon leaving the game { List <PlayerInfo> TDPlayers = new List <PlayerInfo>(PlayerDB.PlayerInfoList.Where(r => (r.isOnBlueTeam || r.isOnRedTeam) && r.IsOnline).ToArray()); for (int i = 0; i < TDPlayers.Count(); i++) { string p1 = TDPlayers[i].Name.ToString(); PlayerInfo pI = PlayerDB.FindPlayerInfoExact(p1); Player p = pI.PlayerObject; if (p != null) { p.iName = null; pI.tempDisplayedName = null; pI.isOnRedTeam = false; pI.isOnBlueTeam = false; pI.isPlayingTD = false; pI.Health = 100; p.entityChanged = true; //reset all special messages if (p.usesCPE) { p.Send(PacketWriter.MakeSpecialMessage((byte)100, "&f")); p.Send(PacketWriter.MakeSpecialMessage((byte)1, "&f")); p.Send(PacketWriter.MakeSpecialMessage((byte)2, "&f")); } //undo gunmode (taken from GunHandler.cs) p.GunMode = false; try { foreach (Vector3I block in p.GunCache.Values) { p.Send(PacketWriter.MakeSetBlock(block.X, block.Y, block.Z, p.WorldMap.GetBlock(block))); Vector3I removed; p.GunCache.TryRemove(block.ToString(), out removed); } if (p.bluePortal.Count > 0) { int j = 0; foreach (Vector3I block in p.bluePortal) { if (p.WorldMap != null && p.World.IsLoaded) { p.WorldMap.QueueUpdate(new BlockUpdate(null, block, p.blueOld[j])); j++; } } p.blueOld.Clear(); p.bluePortal.Clear(); } if (p.orangePortal.Count > 0) { int j = 0; foreach (Vector3I block in p.orangePortal) { if (p.WorldMap != null && p.World.IsLoaded) { p.WorldMap.QueueUpdate(new BlockUpdate(null, block, p.orangeOld[j])); j++; } } p.orangeOld.Clear(); p.orangePortal.Clear(); } } catch (Exception ex) { Logger.Log(LogType.SeriousError, "" + ex); } if (p.IsOnline) { p.Message("Your status has been reverted."); } } } }
/// <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); }
// 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); while (packetsSent < maxPacketsPerUpdate) { BlockUpdate update; if (!updates.TryDequeue(out update)) { if (World.IsFlushing) { canFlush = true; } break; } 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) { //non classicube players get fallbacks instead of the real blocks Packet packet = PacketWriter.MakeSetBlock(update.X, update.Y, update.Z, update.BlockType); Packet packet2 = PacketWriter.MakeSetBlock(update.X, update.Y, update.Z, Map.GetFallbackBlock(update.BlockType)); World.Players.Where(p => p.usesCPE).SendLowPriority(update.Origin, packet); World.Players.Where(p => !p.usesCPE).SendLowPriority(update.Origin, packet2); } 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> Gets the block from given location in player's world, and sends it (sync) to the player. /// Used to undo player's attempted block placement/deletion. /// To avoid threading issues, only use this from this player's IoThread. </summary> internal void RevertBlockNow(short x, short y, short h) { Session.SendNow(PacketWriter.MakeSetBlock(x, y, h, World.Map.GetBlockByte(x, y, h))); }
/// <summary> Gets the block from given location in player's world, and sends it (async) to the player. /// Used to undo player's attempted block placement/deletion. </summary> public void RevertBlock(short x, short y, short h) { Session.SendDelayed(PacketWriter.MakeSetBlock(x, y, h, World.Map.GetBlockByte(x, y, h))); }
public static void RevertGun() //Reverts names for online players. Offline players get reverted upon leaving the game { List <PlayerInfo> FFAPlayers = new List <PlayerInfo>(PlayerDB.PlayerInfoList.Where(r => (r.isPlayingFFA) && r.IsOnline).ToArray()); foreach (PlayerInfo pI in FFAPlayers) { Player p = pI.PlayerObject; p.JoinWorld(p.World, WorldChangeReason.Rejoin); //reset all special messages if (p.SupportsMessageTypes) { p.Send(PacketWriter.MakeSpecialMessage((byte)100, "&f")); p.Send(PacketWriter.MakeSpecialMessage((byte)1, "&f")); p.Send(PacketWriter.MakeSpecialMessage((byte)2, "&f")); } pI.isPlayingFFA = false; if (pI != null) { //undo gunmode (taken from GunHandler.cs) p.GunMode = false; try { foreach (Vector3I block in p.GunCache.Values) { p.Send(PacketWriter.MakeSetBlock(block.X, block.Y, block.Z, p.WorldMap.GetBlock(block))); Vector3I removed; p.GunCache.TryRemove(block.ToString(), out removed); } if (p.bluePortal.Count > 0) { int j = 0; foreach (Vector3I block in p.bluePortal) { if (p.WorldMap != null && p.World.IsLoaded) { p.WorldMap.QueueUpdate(new BlockUpdate(null, block, p.blueOld[j])); j++; } } p.blueOld.Clear(); p.bluePortal.Clear(); } if (p.orangePortal.Count > 0) { int j = 0; foreach (Vector3I block in p.orangePortal) { if (p.WorldMap != null && p.World.IsLoaded) { p.WorldMap.QueueUpdate(new BlockUpdate(null, block, p.orangeOld[j])); j++; } } p.orangeOld.Clear(); p.orangePortal.Clear(); } } catch (Exception ex) { Logger.Log(LogType.SeriousError, "" + ex); } if (p.IsOnline) { p.Message("Your status has been reverted."); } } } }
// 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); } }
// Handles building/deleting by the player public void SetTile(short x, short y, short h, bool buildMode, Block type) { if (CheckBlockSpam()) { return; } if (world.lockDown) { 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) { session.SendNow(PacketWriter.MakeSetBlock(x, y, h, world.map.GetBlock(x, y, h))); return; } foreach (Zone zone in world.map.zones) { if (zone.Contains(x, y, h)) { if (!zone.CanBuild(this)) { session.SendNow(PacketWriter.MakeSetBlock(x, y, h, world.map.GetBlock(x, y, h))); Message("You are not allowed to build in this zone (" + zone.name + ")."); return; } } } // action block handling if (marksExpected > 0) { session.SendNow(PacketWriter.MakeSetBlock(x, y, h, world.map.GetBlock(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; } 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.Lava; } 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.Water; } break; default: update = false; break; } // check if the user has the permission to BUILD the block if (buildMode || replaceMode) { if (type == Block.Lava || type == Block.StillLava) { can = Can(Permissions.PlaceLava); } else if (type == Block.Water || type == Block.StillWater) { can = Can(Permissions.PlaceWater); } else if (type == Block.Admincrete) { can = Can(Permissions.PlaceAdmincrete); } else { can = 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 &= Can(Permissions.Delete); } // if all is well, try placing it if (can) { if (type == Block.Stair && h > 0 && world.map.GetBlock(x, y, h - 1) == (byte)Block.Stair) { session.SendNow(PacketWriter.MakeSetBlock(x, y, h - 1, (byte)Block.DoubleStair)); session.SendNow(PacketWriter.MakeSetBlock(x, y, h, (byte)Block.Air)); world.map.QueueUpdate(new BlockUpdate(this, x, y, h - 1, (byte)Block.DoubleStair)); } else { world.map.QueueUpdate(new BlockUpdate(this, x, y, h, (byte)type)); if (update || replaceMode) { session.SendNow(PacketWriter.MakeSetBlock(x, y, h, (byte)type)); } } } else { Message(Color.Red, "You are not permitted to do that."); session.SendNow(PacketWriter.MakeSetBlock(x, y, h, world.map.GetBlock(x, y, h))); } }