/// <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); }
// 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))); } }