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