static void DrawEllipsoid( Player player, Position[] marks, object tag ) {
player.drawingInProgress = true;
Block drawBlock = (Block)tag;
// find start/end coordinates
int sx = Math.Min( marks[0].x, marks[1].x );
int ex = Math.Max( marks[0].x, marks[1].x );
int sy = Math.Min( marks[0].y, marks[1].y );
int ey = Math.Max( marks[0].y, marks[1].y );
int sh = Math.Min( marks[0].h, marks[1].h );
int eh = Math.Max( marks[0].h, marks[1].h );
int blocks;
byte block;
int step = 8;
blocks = (ex - sx + 1) * (ey - sy + 1) * (eh - sh + 1);
if( blocks > 2000000 ) {
player.Message( "NOTE: This draw command is too massive to undo." );
}
// find axis lengths
double rx = (ex - sx + 1) / 2 + .25;
double ry = (ey - sy + 1) / 2 + .25;
double rh = (eh - sh + 1) / 2 + .25;
double rx2 = 1 / (rx * rx);
double ry2 = 1 / (ry * ry);
double rh2 = 1 / (rh * rh);
// find center points
double cx = (ex + sx) / 2;
double cy = (ey + sy) / 2;
double ch = (eh + sh) / 2;
// prepare to draw
player.drawUndoBuffer.Clear();
blocks = (int)(Math.PI * 0.75 * rx * ry * rh);
if( blocks > 2000000 ) {
player.Message( "NOTE: This draw command is too massive to undo." );
}
for( int x = sx; x <= ex; x += step ) {
for( int y = sy; y <= ey; y += step ) {
for( int h = sh; h <= eh; h += step ) {
for( int h3 = 0; h3 < step && h + h3 <= eh; h3++ ) {
for( int y3 = 0; y3 < step && y + y3 <= ey; y3++ ) {
for( int x3 = 0; x3 < step && x + x3 <= ex; x3++ ) {
// get relative coordinates
double dx = (x + x3 - cx);
double dy = (y + y3 - cy);
double dh = (h + h3 - ch);
// test if it's inside ellipse
if( (dx * dx) * rx2 + (dy * dy) * ry2 + (dh * dh) * rh2 <= 1 ) {
block = player.world.map.GetBlock( x + x3, y + y3, h + h3 );
if( block == (byte)drawBlock ) continue;
if( block == (byte)Block.Admincrete && !player.Can( Permissions.DeleteAdmincrete ) ) continue;
player.drawUndoBuffer.Enqueue( new BlockUpdate( Player.Console, x + x3, y + y3, h + h3, block ) );
player.world.map.QueueUpdate( new BlockUpdate( Player.Console, x + x3, y + y3, h + h3, (byte)drawBlock ) );
}
}
}
}
}
}
}
player.drawingInProgress = false;
player.Message( "Drawing " + blocks + " blocks... The map is now being updated." );
player.world.log.Log( "{0} initiated drawing a cuboid containing {1} blocks of type {2}.", LogType.UserActivity,
player.name,
blocks,
drawBlock.ToString() );
GC.Collect();
}
}