static void CopyCallback([NotNull] Player player, [NotNull] Vector3I[] marks, [NotNull] object tag) { 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 sz = Math.Min(marks[0].Z, marks[1].Z); int ez = Math.Max(marks[0].Z, marks[1].Z); BoundingBox bounds = new BoundingBox(sx, sy, sz, ex, ey, ez); int volume = bounds.Volume; if (!player.CanDraw(volume)) { player.MessageNow( "You are only allowed to run commands that affect up to {0} blocks. This one would affect {1} blocks.", player.Info.Rank.DrawLimit, volume); return; } // remember dimensions and orientation CopyState copyInfo = new CopyState(marks[0], marks[1]); Map map = player.WorldMap; World playerWorld = player.World; if (playerWorld == null) { PlayerOpException.ThrowNoWorld(player); } for (int x = sx; x <= ex; x++) { for (int y = sy; y <= ey; y++) { for (int z = sz; z <= ez; z++) { copyInfo.Blocks[x - sx, y - sy, z - sz] = map.GetBlock(x, y, z); } } } copyInfo.OriginWorld = playerWorld.Name; copyInfo.CopyTime = DateTime.UtcNow; player.SetCopyState(copyInfo); player.MessageNow("{0} blocks copied into slot #{1}, origin at {2} corner. You can now &H/Paste", volume, player.CopySlot + 1, copyInfo.OriginCorner); Logger.Log(LogType.UserActivity, "{0} copied {1} blocks from world {2} (between {3} and {4}).", player.Name, volume, playerWorld.Name, bounds.MinVertex, bounds.MaxVertex); }
public void Draw(Bitmap img) { //guess how big the draw will be int white = System.Drawing.Color.White.ToArgb(); int left, right, top, bottom; int count = Crop(img, out left, out right, out top, out bottom); //check if player can make the drawing if (!player.CanDraw(count)) { player.Message(String.Format("You are only allowed to run commands that affect up to {0} blocks. " + "This one would affect {1} blocks.", player.Info.Rank.DrawLimit, count)); return; } int dirX = 0, dirY = 0; if (direction == Direction.PlusX) { dirX = 1; } if (direction == Direction.MinusX) { dirX = -1; } if (direction == Direction.PlusZ) { dirY = 1; } if (direction == Direction.MinusZ) { dirY = -1; } if (dirX == 0 && dirY == 0) { return; //if blockcount = 0, message is shown and returned } for (int yy = top; yy <= bottom; yy++) { for (int xx = left; xx <= right; xx++) { if (img.GetPixel(xx, yy).ToArgb() == white) { continue; } int dx = xx - left, dy = bottom - yy; Vector3I coords = new Vector3I(origin.X + dirX * dx, origin.Y + dirY * dx, origin.Z + dy); BuildingCommands.DrawOneBlock( player, player.World.Map, blockColor, coords, BlockChangeContext.Drawn, ref blocks, ref blocksDenied, undoState); blockCount++; } } }
private static void DrawOperationCallback(Player player, Vector3I[] marks, object tag) { DrawOperation operation = ( DrawOperation )tag; if (operation.Prepare(marks)) { if (!player.CanDraw(operation.BlocksTotalEstimate)) { player.Message("You are only allowed to run draw commands that affect up to {0} blocks. This one would affect {1} blocks.", new object[] { player.Info.Rank.DrawLimit, operation.Bounds.Volume }); operation.Cancel(); } else { player.Message("{0}: Processing ~{1} blocks.", new object[] { operation.Description, operation.BlocksTotalEstimate }); operation.Begin(); } } }
static void PortalCreateCallback(Player player, Vector3I[] marks, object tag) { try { World world = WorldManager.FindWorldExact(player.PortalWorld); if (world != null) { DrawOperation op = (DrawOperation)tag; if (!op.Prepare(marks)) return; if (!player.CanDraw(op.BlocksTotalEstimate)) { player.MessageNow("You are only allowed to run draw commands that affect up to {0} blocks. This one would affect {1} blocks.", player.Info.Rank.DrawLimit, op.Bounds.Volume); op.Cancel(); return; } int Xmin = Math.Min(marks[0].X, marks[1].X); int Xmax = Math.Max(marks[0].X, marks[1].X); int Ymin = Math.Min(marks[0].Y, marks[1].Y); int Ymax = Math.Max(marks[0].Y, marks[1].Y); int Zmin = Math.Min(marks[0].Z, marks[1].Z); int Zmax = Math.Max(marks[0].Z, marks[1].Z); for (int x = Xmin; x <= Xmax; x++) { for (int y = Ymin; y <= Ymax; y++) { for (int z = Zmin; z <= Zmax; z++) { if (PortalHandler.IsInRangeOfSpawnpoint(player.World, new Vector3I(x, y, z))) { player.Message("You can not build a portal near a spawnpoint."); return; } if (PortalHandler.GetInstance().GetPortal(player.World, new Vector3I(x, y, z)) != null) { player.Message("You can not build a portal inside a portal, U MAD BRO?"); return; } } } } if (player.PortalName == null) { player.PortalName = Portal.GenerateName(player.World); } Portal portal = new Portal(player.PortalWorld, marks, player.PortalName, player.Name, player.World.Name); PortalHandler.CreatePortal(portal, player.World); op.AnnounceCompletion = false; op.Context = BlockChangeContext.Portal; op.Begin(); player.Message("Successfully created portal with name " + portal.Name + "."); } else { player.MessageInvalidWorldName(player.PortalWorld); } } catch (Exception ex) { player.Message("Failed to create portal."); Logger.Log(LogType.Error, "WorldCommands.PortalCreateCallback: " + ex); } }
private static void DrawOperationCallback(Player player, Vector3I[] marks, object tag) { DrawOperation operation = (DrawOperation)tag; if (operation.Prepare(marks)) { if (!player.CanDraw(operation.BlocksTotalEstimate)) { player.Message("You are only allowed to run draw commands that affect up to {0} blocks. This one would affect {1} blocks.", new object[] { player.Info.Rank.DrawLimit, operation.Bounds.Volume }); operation.Cancel(); } else { player.Message("{0}: Processing ~{1} blocks.", new object[] { operation.Description, operation.BlocksTotalEstimate }); operation.Begin(); } } }
static void TreeHandler( Player player, Command cmd ) { string shapeName = cmd.Next(); int height; Forester.TreeShape shape; // that's one ugly if statement... does the job though. if ( shapeName == null || !cmd.NextInt( out height ) || !EnumUtil.TryParse( shapeName, out shape, true ) || shape == Forester.TreeShape.Stickly || shape == Forester.TreeShape.Procedural ) { CdTree.PrintUsage( player ); player.Message( "Available shapes: Normal, Bamboo, Palm, Cone, Round, Rainforest, Mangrove." ); return; } if ( height < 6 || height > 1024 ) { player.Message( "Tree height must be 6 blocks or above" ); return; } int volume = ( int )Math.Pow( height, 3 ); if ( !player.CanDraw( volume ) ) { player.Message( String.Format( "You are only allowed to run commands that affect up to {0} blocks. This one would affect {1} blocks.", player.Info.Rank.DrawLimit, volume ) ); return; } Map map = player.World.Map; ForesterArgs args = new ForesterArgs { Height = height - 1, Operation = Forester.ForesterOperation.Add, Map = map, Shape = shape, TreeCount = 1, RootButtresses = false, Roots = Forester.RootMode.None, Rand = new Random() }; player.SelectionStart( 1, TreeCallback, args, CdTree.Permissions ); player.MessageNow( "Tree: Place a block or type /Mark to use your location." ); }
/* internal static void EllipsoidHollowCallback( Player player, Position[] marks, object tag ) { byte drawBlock = (byte)tag; if( drawBlock == (byte)Block.Undefined ) { drawBlock = (byte)player.LastUsedBlockType; } // 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 ); // find axis lengths double rx = (ex - sx + 1) / 2d; double ry = (ey - sy + 1) / 2d; double rh = (eh - sh + 1) / 2d; double rx2 = 1 / (rx * rx); double ry2 = 1 / (ry * ry); double rh2 = 1 / (rh * rh); // find center points double cx = (ex + sx) / 2d; double cy = (ey + sy) / 2d; double ch = (eh + sh) / 2d; // rougher estimation than the non-hollow form, a voxelized surface is a bit funky int volume = (int)(4 / 3d * Math.PI * ((rx + .5) * (ry + .5) * (rh + .5) - (rx - .5) * (ry - .5) * (rh - .5)) * 0.85); if( !player.CanDraw( volume ) ) { player.MessageNow( "You are only allowed to run draw commands that affect up to {0} blocks. This one would affect {1} blocks.", player.Info.Rank.DrawLimit, volume ); return; } player.UndoBuffer.Clear(); int blocks = 0, blocksDenied = 0; bool cannotUndo = false; for( int x = sx; x <= ex; x++ ) { for( int y = sy; y <= ey; y++ ) { for( int h = sh; h <= eh; h++ ) { double dx = (x - cx); double dy = (y - cy); double dh = (h - ch); if( (dx * dx) * rx2 + (dy * dy) * ry2 + (dh * dh) * rh2 <= 1 ) { // we touched the surface // keep drilling until we hit an internal block do { DrawOneBlock( player, drawBlock, x, y, h, ref blocks, ref blocksDenied, ref cannotUndo ); DrawOneBlock( player, drawBlock, x, y, (int)(ch - dh), ref blocks, ref blocksDenied, ref cannotUndo ); dh = (++h - ch); } while( h <= (int)ch && ((dx + 1) * (dx + 1) * rx2 + (dy * dy) * ry2 + (dh * dh) * rh2 > 1 || (dx - 1) * (dx - 1) * rx2 + (dy * dy) * ry2 + (dh * dh) * rh2 > 1 || (dx * dx) * rx2 + (dy + 1) * (dy + 1) * ry2 + (dh * dh) * rh2 > 1 || (dx * dx) * rx2 + (dy - 1) * (dy - 1) * ry2 + (dh * dh) * rh2 > 1 || (dx * dx) * rx2 + (dy * dy) * ry2 + (dh + 1) * (dh + 1) * rh2 > 1 || (dx * dx) * rx2 + (dy * dy) * ry2 + (dh - 1) * (dh - 1) * rh2 > 1) ); break; } } } } Logger.Log( "{0} drew a hollow ellipsoid containing {1} blocks of type {2} (on world {3})", LogType.UserActivity, player.Name, blocks, (Block)drawBlock, player.World.Name ); DrawingFinished( player, "drawn", blocks, blocksDenied ); } */ internal static void EllipsoidHollowCallback( Player player, Position[] marks, object tag ) { HollowShapeArgs args = (HollowShapeArgs)tag; byte drawBlock = (byte)args.OuterBlock; if( drawBlock == (byte)Block.Undefined ) { drawBlock = (byte)player.GetBind( player.LastUsedBlockType ); } // 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 ); bool fillInner = (args.InnerBlock != Block.Undefined && (ex - sx) > 1 && (ey - sy) > 1 && (eh - sh) > 1); // find axis lengths double rx = (ex - sx + 1) / 2d; double ry = (ey - sy + 1) / 2d; double rh = (eh - sh + 1) / 2d; double rx2 = 1 / (rx * rx); double ry2 = 1 / (ry * ry); double rh2 = 1 / (rh * rh); // find center points double cx = (ex + sx) / 2d; double cy = (ey + sy) / 2d; double ch = (eh + sh) / 2d; int volume; if( fillInner ) { volume = (int)(4 / 3d * Math.PI * rx * ry * rh); } else { // rougher estimation than the non-hollow form, a voxelized surface is a bit funky volume = (int)(4 / 3d * Math.PI * ((rx + .5) * (ry + .5) * (rh + .5) - (rx - .5) * (ry - .5) * (rh - .5)) * 0.85); } if( !player.CanDraw( volume ) ) { player.MessageNow( "You are only allowed to run draw commands that affect up to {0} blocks. This one would affect {1} blocks.", player.Info.Rank.DrawLimit, volume ); return; } player.UndoBuffer.Clear(); int blocks = 0, blocksDenied = 0; bool cannotUndo = false; for( int x = sx; x <= ex; x++ ) { for( int y = sy; y <= ey; y++ ) { for( int h = sh; h <= eh; h++ ) { double dx = (x - cx); double dy = (y - cy); double dh = (h - ch); if( (dx * dx) * rx2 + (dy * dy) * ry2 + (dh * dh) * rh2 > 1 ) continue; // we touched the surface // keep drilling until we hit an internal block do { DrawOneBlock( player, drawBlock, x, y, h, ref blocks, ref blocksDenied, ref cannotUndo ); DrawOneBlock( player, drawBlock, x, y, (int)(ch - dh), ref blocks, ref blocksDenied, ref cannotUndo ); dh = (++h - ch); } while( h <= (int)ch && ((dx + 1) * (dx + 1) * rx2 + (dy * dy) * ry2 + (dh * dh) * rh2 > 1 || (dx - 1) * (dx - 1) * rx2 + (dy * dy) * ry2 + (dh * dh) * rh2 > 1 || (dx * dx) * rx2 + (dy + 1) * (dy + 1) * ry2 + (dh * dh) * rh2 > 1 || (dx * dx) * rx2 + (dy - 1) * (dy - 1) * ry2 + (dh * dh) * rh2 > 1 || (dx * dx) * rx2 + (dy * dy) * ry2 + (dh + 1) * (dh + 1) * rh2 > 1 || (dx * dx) * rx2 + (dy * dy) * ry2 + (dh - 1) * (dh - 1) * rh2 > 1) ); if( fillInner ) { for( ; h <= (int)(ch - dh); h++ ) { DrawOneBlock( player, (byte)args.InnerBlock, x, y, h, ref blocks, ref blocksDenied, ref cannotUndo ); } } break; } } } Logger.Log( "{0} drew a hollow ellipsoid containing {1} blocks of type {2} (on world {3})", LogType.UserActivity, player.Name, blocks, (Block)drawBlock, player.World.Name ); DrawingFinished( player, "drawn", blocks, blocksDenied ); }
static void DrawOperationCallback( Player player, Vector3I[] marks, object tag ) { DrawOperation op = (DrawOperation)tag; if( !op.Prepare( marks ) ) return; if( !player.CanDraw( op.BlocksTotalEstimate ) ) { player.MessageNow( "You are only allowed to run draw commands that affect up to {0} blocks. This one would affect {1} blocks.", player.Info.Rank.DrawLimit, op.Bounds.Volume ); op.Cancel(); return; } player.Message( "{0}: Processing ~{1} blocks.", op.Description, op.BlocksTotalEstimate ); op.Begin(); }
unsafe internal static void ReplaceCallback( Player player, Position[] marks, object drawArgs ) { ReplaceArgs args = (ReplaceArgs)drawArgs; byte* specialTypes = stackalloc byte[args.Types.Length]; int specialTypeCount = args.Types.Length; for( int i = 0; i < args.Types.Length; i++ ) { specialTypes[i] = (byte)args.Types[i]; } bool doExclude = args.DoExclude; // 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 volume = (ex - sx + 1) * (ey - sy + 1) * (eh - sh + 1); if( !player.CanDraw( volume ) ) { player.MessageNow( "You are only allowed to run draw commands that affect up to {0} blocks. This one would affect {1} blocks.", player.Info.Rank.DrawLimit, volume ); return; } player.UndoBuffer.Clear(); bool cannotUndo = false; int blocks = 0, blocksDenied = 0; for( int x = sx; x <= ex; x += DrawStride ) { for( int y = sy; y <= ey; y += DrawStride ) { for( int h = sh; h <= eh; h++ ) { for( int y3 = 0; y3 < DrawStride && y + y3 <= ey; y3++ ) { for( int x3 = 0; x3 < DrawStride && x + x3 <= ex; x3++ ) { byte block = player.World.Map.GetBlockByte( x + x3, y + y3, h ); bool skip = !args.DoExclude; for( int i = 0; i < specialTypeCount; i++ ) { if( block == specialTypes[i] ) { skip = args.DoExclude; break; } } if( skip ) continue; if( player.CanPlace( x + x3, y + y3, h, args.ReplacementBlock, false ) != CanPlaceResult.Allowed ) { blocksDenied++; continue; } player.World.Map.QueueUpdate( new BlockUpdate( null, x + x3, y + y3, h, args.ReplacementBlock ) ); Server.RaisePlayerPlacedBlockEvent( player, (short)x, (short)y, (short)h, (Block)block, args.ReplacementBlock, false ); if( blocks < MaxUndoCount ) { player.UndoBuffer.Enqueue( new BlockUpdate( null, x + x3, y + y3, h, block ) ); } else if( !cannotUndo ) { player.UndoBuffer.Clear(); player.UndoBuffer.TrimExcess(); player.MessageNow( "NOTE: This draw command is too massive to undo." ); cannotUndo = true; if( player.Can( Permission.ManageWorlds ) ) { player.MessageNow( "Reminder: You can use &H/wflush&S to accelerate draw commands." ); } } blocks++; } } } } } Logger.Log( "{0} replaced {1} blocks {2} ({3}) with {4} (on world {5})", LogType.UserActivity, player.Name, blocks, (doExclude ? "except" : "of"), args.Types.JoinToString(), args.ReplacementBlock, player.World.Name ); DrawingFinished( player, "replaced", blocks, blocksDenied ); }
internal static void CuboidHollowCallback( Player player, Position[] marks, object tag ) { HollowShapeArgs args = (HollowShapeArgs)tag; byte drawBlock = (byte)args.OuterBlock; if( drawBlock == (byte)Block.Undefined ) { drawBlock = (byte)player.GetBind( player.LastUsedBlockType ); } // 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 ); bool fillInner = (args.InnerBlock != Block.Undefined && (ex - sx) > 1 && (ey - sy) > 1 && (eh - sh) > 1); int volume = (ex - sx + 1) * (ey - sy + 1) * (eh - sh + 1); if( !fillInner ) { volume -= (ex - sx - 1) * (ey - sy - 1) * (eh - sh - 1); } if( !player.CanDraw( volume ) ) { player.MessageNow( "You are only allowed to run draw commands that affect up to {0} blocks. This one would affect {1} blocks.", player.Info.Rank.DrawLimit, volume ); return; } player.UndoBuffer.Clear(); int blocks = 0, blocksDenied = 0; bool cannotUndo = false; for( int x = sx; x <= ex; x++ ) { for( int y = sy; y <= ey; y++ ) { DrawOneBlock( player, drawBlock, x, y, sh, ref blocks, ref blocksDenied, ref cannotUndo ); DrawOneBlock( player, drawBlock, x, y, eh, ref blocks, ref blocksDenied, ref cannotUndo ); } } for( int x = sx; x <= ex; x++ ) { for( int h = sh; h <= eh; h++ ) { DrawOneBlock( player, drawBlock, x, sy, h, ref blocks, ref blocksDenied, ref cannotUndo ); DrawOneBlock( player, drawBlock, x, ey, h, ref blocks, ref blocksDenied, ref cannotUndo ); } } for( int y = sy; y <= ey; y++ ) { for( int h = sh; h <= eh; h++ ) { DrawOneBlock( player, drawBlock, sx, y, h, ref blocks, ref blocksDenied, ref cannotUndo ); DrawOneBlock( player, drawBlock, ex, y, h, ref blocks, ref blocksDenied, ref cannotUndo ); } } if( fillInner ) { for( int x = sx + 1; x < ex; x += DrawStride ) { for( int y = sy + 1; y < ey; y += DrawStride ) { for( int h = sh + 1; h < eh; h++ ) { for( int y3 = 0; y3 < DrawStride && y + y3 < ey; y3++ ) { for( int x3 = 0; x3 < DrawStride && x + x3 < ex; x3++ ) { DrawOneBlock( player, (byte)args.InnerBlock, x + x3, y + y3, h, ref blocks, ref blocksDenied, ref cannotUndo ); } } } } } } Logger.Log( "{0} drew a hollow cuboid containing {1} blocks of type {2} (on world {3})", LogType.UserActivity, player.Name, blocks, (Block)drawBlock, player.World.Name ); DrawingFinished( player, "drawn", blocks, blocksDenied ); }
internal static void CuboidWireframeCallback( Player player, Position[] marks, object tag ) { byte drawBlock = (byte)tag; if( drawBlock == (byte)Block.Undefined ) { drawBlock = (byte)player.GetBind( player.LastUsedBlockType ); } // 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 ); // Calculate the upper limit on the volume int solidVolume = (ex - sx + 1) * (ey - sy + 1) * (eh - sh + 1); int hollowVolume = Math.Max( 0, ex - sx - 1 ) * Math.Max( 0, ey - sy - 1 ) * Math.Max( 0, eh - sh - 1 ); int sideVolume = Math.Max( 0, ex - sx - 1 ) * Math.Max( 0, ey - sy - 1 ) * (ex != sx ? 2 : 1) + Math.Max( 0, ey - sy - 1 ) * Math.Max( 0, eh - sh - 1 ) * (ey != sy ? 2 : 1) + Math.Max( 0, eh - sh - 1 ) * Math.Max( 0, ex - sx - 1 ) * (eh != sh ? 2 : 1); int volume = solidVolume - hollowVolume - sideVolume; if( !player.CanDraw( volume ) ) { player.MessageNow( "You are only allowed to run draw commands that affect up to {0} blocks. This one would affect {1} blocks.", player.Info.Rank.DrawLimit, volume ); return; } player.UndoBuffer.Clear(); int blocks = 0, blocksDenied = 0; bool cannotUndo = false; // Draw cuboid vertices DrawOneBlock( player, drawBlock, sx, sy, sh, ref blocks, ref blocksDenied, ref cannotUndo ); if( sx != ex ) DrawOneBlock( player, drawBlock, ex, sy, sh, ref blocks, ref blocksDenied, ref cannotUndo ); if( sy != ey ) DrawOneBlock( player, drawBlock, sx, ey, sh, ref blocks, ref blocksDenied, ref cannotUndo ); if( sx != ex && sy != ey ) DrawOneBlock( player, drawBlock, ex, ey, sh, ref blocks, ref blocksDenied, ref cannotUndo ); if( sh != eh ) DrawOneBlock( player, drawBlock, sx, sy, eh, ref blocks, ref blocksDenied, ref cannotUndo ); if( sx != ex && sh != eh ) DrawOneBlock( player, drawBlock, ex, sy, eh, ref blocks, ref blocksDenied, ref cannotUndo ); if( sy != ey && sh != eh ) DrawOneBlock( player, drawBlock, sx, ey, eh, ref blocks, ref blocksDenied, ref cannotUndo ); if( sx != ex && sy != ey && sh != eh ) DrawOneBlock( player, drawBlock, ex, ey, eh, ref blocks, ref blocksDenied, ref cannotUndo ); // Draw edges along the X axis if( ex - sx > 1 ) { for( int x = sx + 1; x < ex; x++ ) { DrawOneBlock( player, drawBlock, x, sy, sh, ref blocks, ref blocksDenied, ref cannotUndo ); if( sh != eh ) DrawOneBlock( player, drawBlock, x, sy, eh, ref blocks, ref blocksDenied, ref cannotUndo ); if( sy != ey ) { DrawOneBlock( player, drawBlock, x, ey, sh, ref blocks, ref blocksDenied, ref cannotUndo ); if( sh != eh ) DrawOneBlock( player, drawBlock, x, ey, eh, ref blocks, ref blocksDenied, ref cannotUndo ); } } } // Draw edges along the Y axis if( ey - sy > 1 ) { for( int y = sy + 1; y < ey; y++ ) { DrawOneBlock( player, drawBlock, sx, y, sh, ref blocks, ref blocksDenied, ref cannotUndo ); if( sh != eh ) DrawOneBlock( player, drawBlock, sx, y, eh, ref blocks, ref blocksDenied, ref cannotUndo ); if( sx != ex ) { DrawOneBlock( player, drawBlock, ex, y, sh, ref blocks, ref blocksDenied, ref cannotUndo ); if( sh != eh ) DrawOneBlock( player, drawBlock, ex, y, eh, ref blocks, ref blocksDenied, ref cannotUndo ); } } } // Draw edges along the H axis if( eh - sh > 1 ) { for( int h = sh + 1; h < eh; h++ ) { DrawOneBlock( player, drawBlock, sx, sy, h, ref blocks, ref blocksDenied, ref cannotUndo ); if( sy != ey ) DrawOneBlock( player, drawBlock, sx, ey, h, ref blocks, ref blocksDenied, ref cannotUndo ); if( sx != ex ) { DrawOneBlock( player, drawBlock, ex, ey, h, ref blocks, ref blocksDenied, ref cannotUndo ); if( sy != ey ) DrawOneBlock( player, drawBlock, ex, sy, h, ref blocks, ref blocksDenied, ref cannotUndo ); } } } Logger.Log( "{0} drew a wireframe cuboid containing {1} blocks of type {2} (on world {3})", LogType.UserActivity, player.Name, blocks, (Block)drawBlock, player.World.Name ); DrawingFinished( player, "drawn", blocks, blocksDenied ); }
unsafe internal static void PasteCallback( Player player, Position[] marks, object tag ) { CopyInformation info = player.CopyInformation; PasteArgs args = (PasteArgs)tag; byte* specialTypes = stackalloc byte[args.BlockTypes.Length]; int specialTypeCount = args.BlockTypes.Length; for( int i = 0; i < args.BlockTypes.Length; i++ ) { specialTypes[i] = (byte)args.BlockTypes[i]; } Map map = player.World.Map; BoundingBox bounds = new BoundingBox( marks[0], info.WidthX, info.WidthY, info.Height ); int pasteVolume = bounds.GetIntersection( map.Bounds ).Volume; if( !player.CanDraw( pasteVolume ) ) { player.MessageNow( "You are only allowed to run draw commands that affect up to {0} blocks. This one would affect {1} blocks.", player.Info.Rank.DrawLimit, pasteVolume ); return; } if( bounds.XMin < 0 || bounds.XMax > map.WidthX - 1 ) { player.MessageNow( "Warning: Not enough room horizontally (X), paste cut off." ); } if( bounds.YMin < 0 || bounds.YMax > map.WidthY - 1 ) { player.MessageNow( "Warning: Not enough room horizontally (Y), paste cut off." ); } if( bounds.HMin < 0 || bounds.HMax > map.Height - 1 ) { player.MessageNow( "Warning: Not enough room vertically, paste cut off." ); } player.UndoBuffer.Clear(); int blocks = 0, blocksDenied = 0; bool cannotUndo = false; for( int x = bounds.XMin; x <= bounds.XMax; x += DrawStride ) { for( int y = bounds.YMin; y <= bounds.YMax; y += DrawStride ) { for( int h = bounds.HMin; h <= bounds.HMax; h++ ) { for( int y3 = 0; y3 < DrawStride && y + y3 <= bounds.YMax; y3++ ) { for( int x3 = 0; x3 < DrawStride && x + x3 <= bounds.XMax; x3++ ) { byte block = info.Buffer[x + x3 - bounds.XMin, y + y3 - bounds.YMin, h - bounds.HMin]; if( args.DoInclude ) { bool skip = true; for( int i = 0; i < specialTypeCount; i++ ) { if( block == specialTypes[i] ) { skip = false; break; } } if( skip ) continue; } else if( args.DoExclude ) { bool skip = false; for( int i = 0; i < specialTypeCount; i++ ) { if( block == specialTypes[i] ) { skip = true; break; } } if( skip ) continue; } DrawOneBlock( player, block, x + x3, y + y3, h, ref blocks, ref blocksDenied, ref cannotUndo ); } } } } } Logger.Log( "{0} pasted {1} blocks to {2}.", LogType.UserActivity, player.Name, blocks, player.World.Name ); DrawingFinished( player, "pasted", blocks, blocksDenied ); }
internal static void CutCallback( Player player, Position[] marks, object tag ) { 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 ); byte fillType = (byte)tag; int volume = (ex - sx + 1) * (ey - sy + 1) * (eh - sh + 1); if( !player.CanDraw( volume ) ) { player.MessageNow( String.Format( "You are only allowed to run commands that affect up to {0} blocks. This one would affect {1} blocks.", player.Info.Rank.DrawLimit, volume ) ); return; } // remember dimensions and orientation CopyInformation copyInfo = new CopyInformation { WidthX = marks[1].X - marks[0].X, WidthY = marks[1].Y - marks[0].Y, Height = marks[1].H - marks[0].H, Buffer = new byte[ex - sx + 1, ey - sy + 1, eh - sh + 1] }; player.UndoBuffer.Clear(); int blocks = 0, blocksDenied = 0; bool cannotUndo = false; for( int x = sx; x <= ex; x++ ) { for( int y = sy; y <= ey; y++ ) { for( int h = sh; h <= eh; h++ ) { copyInfo.Buffer[x - sx, y - sy, h - sh] = player.World.Map.GetBlockByte( x, y, h ); DrawOneBlock( player, fillType, x, y, h, ref blocks, ref blocksDenied, ref cannotUndo ); } } } player.CopyInformation = copyInfo; player.MessageNow( "{0} blocks were cut. You can now &H/paste", volume ); player.MessageNow( "Origin at {0} {1}{2} corner.", (copyInfo.Height > 0 ? "bottom" : "top"), (copyInfo.WidthY > 0 ? "south" : "north"), (copyInfo.WidthX > 0 ? "west" : "east") ); Logger.Log( "{0} cut {1} blocks from {2}, replacing {3} blocks with {4}.", LogType.UserActivity, player.Name, volume, player.World.Name, blocks, (Block)fillType ); player.UndoBuffer.TrimExcess(); Server.RequestGC(); }
internal static void CopyCallback( Player player, Position[] marks, object tag ) { 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 volume = (ex - sx + 1) * (ey - sy + 1) * (eh - sh + 1); if( !player.CanDraw( volume ) ) { player.MessageNow( String.Format( "You are only allowed to run commands that affect up to {0} blocks. This one would affect {1} blocks.", player.Info.Rank.DrawLimit, volume ) ); return; } // remember dimensions and orientation CopyInformation copyInfo = new CopyInformation { WidthX = marks[1].X - marks[0].X, WidthY = marks[1].Y - marks[0].Y, Height = marks[1].H - marks[0].H, Buffer = new byte[ex - sx + 1, ey - sy + 1, eh - sh + 1] }; for( int x = sx; x <= ex; x++ ) { for( int y = sy; y <= ey; y++ ) { for( int h = sh; h <= eh; h++ ) { copyInfo.Buffer[x - sx, y - sy, h - sh] = player.World.Map.GetBlockByte( x, y, h ); } } } player.CopyInformation = copyInfo; player.MessageNow( "{0} blocks were copied. You can now &H/paste", volume ); player.MessageNow( "Origin at {0} {1}{2} corner.", (copyInfo.Height > 0 ? "bottom" : "top"), (copyInfo.WidthY > 0 ? "south" : "north"), (copyInfo.WidthX > 0 ? "west" : "east") ); Logger.Log( "{0} copied {1} blocks from {2}.", LogType.UserActivity, player.Name, volume, player.World.Name ); }
public void Draw(Bitmap img) { //guess how big the draw will be int Count = 0; for (int x = 0; x < img.Width; x++) { for (int z = 0; z < img.Height; z++) { if (img.GetPixel(x, z).ToArgb() != System.Drawing.Color.White.ToArgb()) { Count++; } } } //check if player can make the drawing if (!player.CanDraw(Count)) { player.MessageNow( String.Format( "You are only allowed to run commands that affect up to {0} blocks. This one would affect {1} blocks.", player.Info.Rank.DrawLimit, Count)); return; } //check direction and draw switch (direction) { case Direction.one: for (int x = 0; x < img.Width; x++) { for (int z = 0; z < img.Height; z++) { if (img.GetPixel(x, z).ToArgb() != System.Drawing.Color.White.ToArgb()) { DrawOneBlock(player, player.World.Map, PixelData.BlockColor, new Vector3I((PixelData.X + x), PixelData.Y, (PixelData.Z + z)), BlockChangeContext.Drawn, ref blocks, ref blocksDenied, undoState); blockCount++; } } } break; case Direction.two: for (int x = 0; x < img.Width; x++) { for (int z = 0; z < img.Height; z++) { if (img.GetPixel(x, z).ToArgb() != System.Drawing.Color.White.ToArgb()) { DrawOneBlock(player, player.World.Map, PixelData.BlockColor, new Vector3I((PixelData.X - x), PixelData.Y, (PixelData.Z + z)), BlockChangeContext.Drawn, ref blocks, ref blocksDenied, undoState); blockCount++; } } } break; case Direction.three: for (int y = 0; y < img.Width; y++) { for (int z = 0; z < img.Height; z++) { if (img.GetPixel(y, z).ToArgb() != System.Drawing.Color.White.ToArgb()) { DrawOneBlock(player, player.World.Map, PixelData.BlockColor, new Vector3I(PixelData.X, (PixelData.Y + y), (PixelData.Z + z)), BlockChangeContext.Drawn, ref blocks, ref blocksDenied, undoState); blockCount++; } } } break; case Direction.four: for (int y = 0; y < img.Width; y++) { for (int z = 0; z < img.Height; z++) { if (img.GetPixel(y, z).ToArgb() != System.Drawing.Color.White.ToArgb()) { DrawOneBlock(player, player.World.Map, PixelData.BlockColor, new Vector3I(PixelData.X, ((PixelData.Y) - y), (PixelData.Z + z)), BlockChangeContext.Drawn, ref blocks, ref blocksDenied, undoState); blockCount++; } } } break; default: break; //if blockcount = 0, message is shown and returned } }
private static void DrawImageCallback(Player player, Vector3I[] marks, object tag) { ImageDrawOperation op = (ImageDrawOperation)tag; player.Message("&HDrawImage: Downloading {0}", op.ImageUrl); try { op.Prepare(marks); if (!player.CanDraw(op.BlocksTotalEstimate)) { player.Message( "DrawImage: You are only allowed to run commands that affect up to {0} blocks. This one would affect {1} blocks.", player.Info.Rank.DrawLimit, op.BlocksTotalEstimate); return; } op.Begin(); } catch (ArgumentException ex) { player.Message("&WDrawImage: Error setting up: " + ex.Message); } catch (Exception ex) { Logger.Log(LogType.Warning, "{0}: Error downloading image from {1}: {2}", op.Description, op.ImageUrl, ex); player.Message("&WDrawImage: Error downloading: " + ex.Message); } }
static void RestoreCallback( Player player, Vector3I[] marks, object tag ) { BoundingBox selection = new BoundingBox( marks[0], marks[1] ); Map map = (Map)tag; if( !player.CanDraw( selection.Volume ) ) { player.MessageNow( "You are only allowed to restore up to {0} blocks at a time. This would affect {1} blocks.", player.Info.Rank.DrawLimit, selection.Volume ); return; } int blocksDrawn = 0, blocksSkipped = 0; UndoState undoState = player.DrawBegin( null ); World playerWorld = player.World; if( playerWorld == null ) PlayerOpException.ThrowNoWorld( player ); Map playerMap = player.WorldMap; Vector3I coord = new Vector3I(); for( coord.X = selection.XMin; coord.X <= selection.XMax; coord.X++ ) { for( coord.Y = selection.YMin; coord.Y <= selection.YMax; coord.Y++ ) { for( coord.Z = selection.ZMin; coord.Z <= selection.ZMax; coord.Z++ ) { DrawOneBlock( player, playerMap, map.GetBlock( coord ), coord, RestoreContext, ref blocksDrawn, ref blocksSkipped, undoState ); } } } Logger.Log( LogType.UserActivity, "{0} restored {1} blocks on world {2} (@{3},{4},{5} - {6},{7},{8}) from file {9}.", player.Name, blocksDrawn, playerWorld.Name, selection.XMin, selection.YMin, selection.ZMin, selection.XMax, selection.YMax, selection.ZMax, map.Metadata["fCraft.Temp", "FileName"] ); DrawingFinished( player, "Restored", blocksDrawn, blocksSkipped ); }
static void DrawOperationCallback( Player player, Vector3I[] marks, object tag ) { DrawOperation op = (DrawOperation)tag; if( !op.Prepare( marks ) ) return; if( !player.Info.ClassicubeVerified ) { player.Message("As you had an older minecraft.net account, you must have an admin verify your " + "new classicube.net account actually is you with /verify before you can use drawing commands."); op.Cancel(); return; } if( !player.CanDraw( op.BlocksTotalEstimate ) ) { player.Message( "You are only allowed to run draw commands that affect up to &f{0}&s blocks. This one would affect &f{1}&s blocks.", player.Info.Rank.DrawLimit, op.Bounds.Volume ); op.Cancel(); return; } player.Message( "{0}: Processing ~&f{1}&s blocks.", op.Description, op.BlocksTotalEstimate ); op.Begin(); }
static void CopyCallback( Player player, Vector3I[] marks, object tag ) { 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 sz = Math.Min( marks[0].Z, marks[1].Z ); int ez = Math.Max( marks[0].Z, marks[1].Z ); BoundingBox bounds = new BoundingBox( sx, sy, sz, ex, ey, ez ); int volume = bounds.Volume; if( !player.CanDraw( volume ) ) { player.MessageNow( "You are only allowed to run commands that affect up to {0} blocks. This one would affect {1} blocks.", player.Info.Rank.DrawLimit, volume ); return; } // remember dimensions and orientation CopyState copyInfo = new CopyState( marks[0], marks[1] ); Map map = player.WorldMap; World playerWorld = player.World; if( playerWorld == null ) PlayerOpException.ThrowNoWorld( player ); for( int x = sx; x <= ex; x++ ) { for( int y = sy; y <= ey; y++ ) { for( int z = sz; z <= ez; z++ ) { copyInfo.Blocks[x - sx, y - sy, z - sz] = map.GetBlock( x, y, z ); } } } copyInfo.OriginWorld = playerWorld.Name; copyInfo.CopyTime = DateTime.UtcNow; player.SetCopyState( copyInfo ); player.MessageNow( "{0} blocks copied into slot #{1}, origin at {2} corner. You can now &H/Paste", volume, player.CopySlot + 1, copyInfo.OriginCorner ); Logger.Log( LogType.UserActivity, "{0} copied {1} blocks from world {2} (between {3} and {4}).", player.Name, volume, playerWorld.Name, bounds.MinVertex, bounds.MaxVertex ); }
internal static void EllipsoidCallback( Player player, Position[] marks, object tag ) { byte drawBlock = (byte)tag; if( drawBlock == (byte)Block.Undefined ) { drawBlock = (byte)player.GetBind( player.LastUsedBlockType ); } // 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 ); // find axis lengths double rx = (ex - sx + 1) / 2d; double ry = (ey - sy + 1) / 2d; double rh = (eh - sh + 1) / 2d; double rx2 = 1 / (rx * rx); double ry2 = 1 / (ry * ry); double rh2 = 1 / (rh * rh); // find center points double cx = (ex + sx) / 2d; double cy = (ey + sy) / 2d; double ch = (eh + sh) / 2d; int volume = (int)(4 / 3d * Math.PI * rx * ry * rh); if( !player.CanDraw( volume ) ) { player.MessageNow( "You are only allowed to run draw commands that affect up to {0} blocks. This one would affect {1} blocks.", player.Info.Rank.DrawLimit, volume ); return; } player.UndoBuffer.Clear(); int blocks = 0, blocksDenied = 0; bool cannotUndo = false; for( int x = sx; x <= ex; x += DrawStride ) { for( int y = sy; y <= ey; y += DrawStride ) { for( int h = sh; h <= eh; h++ ) { for( int y3 = 0; y3 < DrawStride && y + y3 <= ey; y3++ ) { for( int x3 = 0; x3 < DrawStride && x + x3 <= ex; x3++ ) { // get relative coordinates double dx = (x + x3 - cx); double dy = (y + y3 - cy); double dh = (h - ch); // test if it's inside ellipse if( (dx * dx) * rx2 + (dy * dy) * ry2 + (dh * dh) * rh2 <= 1 ) { DrawOneBlock( player, drawBlock, x + x3, y + y3, h, ref blocks, ref blocksDenied, ref cannotUndo ); } } } } } } Logger.Log( "{0} drew an ellipsoid containing {1} blocks of type {2} (on world {3})", LogType.UserActivity, player.Name, blocks, (Block)drawBlock, player.World.Name ); DrawingFinished( player, "drawn", blocks, blocksDenied ); }