bool HandlesPlayers(Player p, CatchPos bp, Vec3U16 pos) { Player pl = GetPlayer(p, pos, true); if (pl == null) { return(false); } if (p.level.physics >= 3 && bp.ending >= EndType.Explode) { pl.HandleDeath(Block.stone, " was blown up by " + p.color + p.DisplayName, true); } else { pl.HandleDeath(Block.stone, " was shot by " + p.color + p.DisplayName); } return(true); }
bool RedFlagCallback(Player p, Vec3S32[] marks, object state, BlockID block) { CTFMapConfig cfg = (CTFMapConfig)state; Vec3U16 P = (Vec3U16)marks[0]; cfg.RedFlagPos = P; p.Message("Set flag position of red team to ({0})", P); block = p.level.GetBlock(P.X, P.Y, P.Z); if (block == Block.Air) { block = Block.Red; } cfg.RedFlagBlock = block; p.Message("Set flag block of red team to {0}", Block.GetName(p, block)); SaveMapConfig(p, cfg); return(false); }
public override void Perform(Vec3S32[] marks, Brush brush, Action <DrawOpBlock> output) { Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); int dx = Math.Abs(p1.X - p2.X), dy = Math.Abs(p1.Y - p2.Y), dz = Math.Abs(p1.Z - p2.Z); byte stepX = 0, stepY = 0, stepZ = 0; if (dx >= dy && dx >= dz) { stepX = 1; } else if (dy > dx && dy > dz) { stepY = 1; } else if (dz > dy && dz > dx) { stepZ = 1; } int i = 12; for (ushort y = p1.Y; y <= p2.Y; y++) { i = (i + stepY) % 13; int startZ = i; for (ushort z = p1.Z; z <= p2.Z; z++) { i = (i + stepZ) % 13; int startX = i; for (ushort x = p1.X; x <= p2.X; x++) { i = (i + stepX) % 13; if (Level.GetTile(x, y, z) != Block.air) { output(Place(x, y, z, (byte)(Block.red + i), 0)); } } i = startX; } i = startZ; } }
protected override bool DoDraw(Player p, Vec3S32[] marks, object state, ushort block) { if (!base.DoDraw(p, marks, state, block)) { return(false); } DrawArgs dArgs = (DrawArgs)state; if (dArgs.Mode != DrawMode.wire) { return(true); } // special for connected line mode p.MakeSelection(MarksCount, "Selecting endpoints for %S" + dArgs.Op.Name, dArgs, DoDraw); Vec3U16 pos = p.lastClick; p.DoBlockchangeCallback(pos.X, pos.Y, pos.Z, p.GetHeldBlock()); return(false); }
/// <summary> Finds all block changes by the given player. </summary> public void FindChangesBy(int id, Action <BlockDBEntry> output, out Vec3U16 dims) { dims = default(Vec3U16); using (IDisposable readLock = locker.AccquireReadLock()) { if (!File.Exists(FilePath)) { return; } using (Stream s = File.OpenRead(FilePath)) { BlockDBFile.ReadHeader(s, out dims); BlockDBFile.IterateBackwards(s, e => { if (e.PlayerID == id) { output(e); } }); } } }
public static BlockDBFile ReadHeader(Stream s, out Vec3U16 dims) { dims = default(Vec3U16); byte[] header = new byte[EntrySize * HeaderEntries]; ReadFully(s, header, 0, header.Length); // Check constants are expected // TODO: check 8 byte string identifier ushort fileVersion = ReadU16(header, 8); if (fileVersion != Version) { throw new NotSupportedException("only version 1 is supported"); } dims.X = ReadU16(header, 10); dims.Y = ReadU16(header, 12); dims.Z = ReadU16(header, 14); return(V1); }
public override void Perform(Vec3U16[] marks, Player p, Level lvl, Brush brush) { Vec3U16 p1 = marks[0], p2 = marks[1]; int lenX = (p2.X - p1.X + 1), lenY = (p2.Y - p1.Y + 1); QuadY(p1.Y, p1.X, p1.Z, p2.X, p2.Z, p, lvl, brush); QuadY(p2.Y, p1.X, p1.Z, p2.X, p2.Z, p, lvl, brush); if (lenY > 2) { QuadX(p1.X, (ushort)(p1.Y + 1), p1.Z, (ushort)(p2.Y - 1), p2.Z, p, lvl, brush); QuadX(p2.X, (ushort)(p1.Y + 1), p1.Z, (ushort)(p2.Y - 1), p2.Z, p, lvl, brush); } if (lenX > 2 && lenY > 2) { QuadZ(p1.Z, (ushort)(p1.Y + 1), (ushort)(p1.X + 1), (ushort)(p2.Y - 1), (ushort)(p2.X - 1), p, lvl, brush); QuadZ(p2.Z, (ushort)(p1.Y + 1), (ushort)(p1.X + 1), (ushort)(p2.Y - 1), (ushort)(p2.X - 1), p, lvl, brush); } }
public override void Perform(Vec3U16[] marks, Player p, Level lvl, Brush brush) { Vec3U16 p1 = marks[0], p2 = marks[1]; while (true) { wallOp.Perform(marks, p, lvl, brush); if (p1.Y >= lvl.Height || Math.Abs(p2.X - p1.X) <= 1 || Math.Abs(p2.Z - p1.Z) <= 1) { break; } p1.X++; p2.X--; p1.Z++; p2.Z--; marks[0] = p1; marks[1] = p2; baseOp.Perform(marks, p, lvl, airBrush); p1.Y = (ushort)(p1.Y + yDir); p2.Y = p1.Y; marks[0] = p1; marks[1] = p2; } }
public override void Perform(Vec3U16[] marks, Player p, Level lvl, Brush brush) { Vec3U16 P = marks[0]; int minX = Math.Max(P.X - Radius, 0) - P.X, maxX = Math.Min(P.X + Radius, lvl.Width - 1) - P.X; int minZ = Math.Max(P.Z - Radius, 0) - P.Z, maxZ = Math.Min(P.Z + Radius, lvl.Length - 1) - P.Z; int maxY = Math.Min(P.Y + Height, lvl.Height - 1) - P.Y; for (int yy = 0; yy <= maxY; yy++) { for (int zz = minZ; zz <= maxZ; zz++) { for (int xx = minX; xx <= maxX; xx++) { int curHeight = Invert ? yy : Height - yy; if (curHeight == 0) { continue; } int cx = P.X + xx, cy = P.Y + (Height - curHeight), cz = P.Z + zz; double curRadius = Radius * ((double)curHeight / (double)Height); int absx = Math.Abs(xx), absz = Math.Abs(zz); if (absx > curRadius || absz > curRadius) { continue; } if (absx < (curRadius - 1) && absz < (curRadius - 1)) { continue; } byte ctile = lvl.GetTile((ushort)cx, (ushort)cy, (ushort)cz); if (ctile != 0) { continue; } PlaceBlock(p, lvl, (ushort)cx, (ushort)cy, (ushort)cz, brush); } } } }
public override Level Read(Stream src, string name, bool metadata) { BinaryReader reader = new BinaryReader(src); Vec3U16 dims = ReadHeader(reader); Level lvl = new Level(name, dims.X, dims.Y, dims.Z); lvl.spawnx = (ushort)(reader.ReadInt32() / 32); lvl.spawny = (ushort)(reader.ReadInt32() / 32); lvl.spawnz = (ushort)(reader.ReadInt32() / 32); lvl.rotx = reader.ReadByte(); lvl.roty = reader.ReadByte(); reader.ReadUInt32(); // date modified reader.ReadUInt32(); // date created reader.ReadBytes(16); // uuid reader.ReadBytes(26); // layer index int metaSize = reader.ReadInt32(); using (DeflateStream ds = new DeflateStream(src, CompressionMode.Decompress)) { reader = new BinaryReader(ds); for (int i = 0; i < metaSize; i++) { string group = ReadString(reader); string key = ReadString(reader); string value = ReadString(reader); if (group != "zones") { continue; } try { ParseZone(lvl, value); } catch (Exception ex) { Logger.LogError("Error importing zone '" + key + "' from fCraft map", ex); } } ReadFully(ds, lvl.blocks, lvl.blocks.Length); } ConvertCustom(lvl); return(lvl); }
void HandlePlayerSpawning(Player p, ref Position pos, ref byte yaw, ref byte pitch, bool respawning) { if (p.level != Map) { return; } CtfTeam team = TeamOf(p); if (team == null) { return; } if (respawning) { DropFlag(p, team); } Vec3U16 coords = team.SpawnPos; pos = Position.FromFeetBlockCoords(coords.X, coords.Y, coords.Z); }
/// <summary> Outputs all block changes by the given players. </summary> /// <remarks> You must lock using Locker.AccquireRead() **before** entering this method. </remarks> /// <returns> whether an entry before start time was reached. </returns> public bool FindChangesBy(int[] ids, DateTime start, DateTime end, out Vec3U16 dims, Action <BlockDBEntry> output) { int startDelta = ClampDelta(start.Subtract(Epoch)); int endDelta = ClampDelta(end.Subtract(Epoch)); dims = Dims; if (FindInMemoryBy(ids, startDelta, endDelta, output)) { return(true); } if (!File.Exists(FilePath)) { return(false); } using (Stream s = OpenRead()) { BlockDBFile format = BlockDBFile.ReadHeader(s, out dims); return(format.FindChangesBy(s, ids, startDelta, endDelta, output)); } }
public override void Perform(Vec3S32[] marks, Brush brush, DrawOpOutput output) { Max.X = Math.Min(Max.X, Source.Width - 1); Max.Y = Math.Min(Max.Y, Source.Height - 1); Max.Z = Math.Min(Max.Z, Source.Length - 1); Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); for (ushort y = p1.Y; y <= p2.Y; y++) { for (ushort z = p1.Z; z <= p2.Z; z++) { for (ushort x = p1.X; x <= p2.X; x++) { output(Place(x, y, z, Source.FastGetBlock(x, y, z))); } } } Source.Dispose(); }
public static byte[] MakeSelection(byte selID, string label, Vec3U16 p1, Vec3U16 p2, short r, short g, short b, short opacity, bool hasCP437) { byte[] buffer = new byte[86]; buffer[0] = Opcode.CpeMakeSelection; buffer[1] = selID; NetUtils.Write(label, buffer, 2, hasCP437); NetUtils.WriteU16(p1.X, buffer, 66); NetUtils.WriteU16(p1.Y, buffer, 68); NetUtils.WriteU16(p1.Z, buffer, 70); NetUtils.WriteU16(p2.X, buffer, 72); NetUtils.WriteU16(p2.Y, buffer, 74); NetUtils.WriteU16(p2.Z, buffer, 76); NetUtils.WriteI16(r, buffer, 78); NetUtils.WriteI16(g, buffer, 80); NetUtils.WriteI16(b, buffer, 82); NetUtils.WriteI16(opacity, buffer, 84); return(buffer); }
public override long GetBlocksAffected(Level lvl, Vec3U16[] marks) { Vec3U16 origP1 = marks[0], origP2 = marks[1]; Vec3U16 p1 = marks[0], p2 = marks[1]; long total = 0; while (true) { total += baseOp.GetBlocksAffected(lvl, marks); if (p1.Y >= lvl.Height || Math.Abs(p2.X - p1.X) <= 1 || Math.Abs(p2.Z - p1.Z) <= 1) { break; } p1.X++; p2.X--; p1.Z++; p2.Z--; p1.Y = (ushort)(p1.Y + yDir); p2.Y = p1.Y; marks[0] = p1; marks[1] = p2; } marks[0] = origP1; marks[1] = origP2; return(total); }
static bool HitsPlayer(WeaponArgs args, Vec3U16 pos) { Player pl = GetPlayer(args.player, pos, true); if (pl == null) { return(false); } Player p = args.player; if (p.level.physics >= 3 && args.weaponType >= WeaponType.Explode) { pl.HandleDeath(Block.Cobblestone, "@p %Swas blown up by " + p.ColoredName, true); } else { pl.HandleDeath(Block.Cobblestone, "@p %Swas shot by " + p.ColoredName); } return(true); }
public override void Perform(Vec3S32[] marks, Brush brush, Action <DrawOpBlock> output) { Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); int lenX = (p2.X - p1.X + 1), lenY = (p2.Y - p1.Y + 1); QuadY(p1.Y, p1.X, p1.Z, p2.X, p2.Z, brush, output); QuadY(p2.Y, p1.X, p1.Z, p2.X, p2.Z, brush, output); if (lenY > 2) { QuadX(p1.X, (ushort)(p1.Y + 1), p1.Z, (ushort)(p2.Y - 1), p2.Z, brush, output); QuadX(p2.X, (ushort)(p1.Y + 1), p1.Z, (ushort)(p2.Y - 1), p2.Z, brush, output); } if (lenX > 2 && lenY > 2) { QuadZ(p1.Z, (ushort)(p1.Y + 1), (ushort)(p1.X + 1), (ushort)(p2.Y - 1), (ushort)(p2.X - 1), brush, output); QuadZ(p2.Z, (ushort)(p1.Y + 1), (ushort)(p1.X + 1), (ushort)(p2.Y - 1), (ushort)(p2.X - 1), brush, output); } }
public override void Perform(Vec3S32[] marks, Brush brush, DrawOpOutput output) { CopyState state = CopyState; bool pasteAir = state.PasteAir; Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); for (ushort y = p1.Y; y <= p2.Y; y++) { for (ushort z = p1.Z; z <= p2.Z; z++) { for (ushort x = p1.X; x <= p2.X; x++) { DrawOpBlock block = Place(x, y, z, brush); if (pasteAir || block.Block.BlockID != Block.Air) { output(block); } } } } }
public override void Perform(Vec3S32[] marks, Brush brush, DrawOpOutput output) { int upper = (Radius + 1) * (Radius + 1); Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); Vec3S32 C = (Min + Max) / 2; for (ushort y = p1.Y; y <= p2.Y; y++) { for (ushort z = p1.Z; z <= p2.Z; z++) { for (ushort x = p1.X; x <= p2.X; x++) { int dist = (C.X - x) * (C.X - x) + (C.Y - y) * (C.Y - y) + (C.Z - z) * (C.Z - z); if (dist < upper) { output(Place(x, y, z, brush)); } } } } }
void PullBack(Player p, Vec3U16 cur, Vec3U16 target, int dirX, int dirZ) { byte type = p.level.GetTile(cur.X, cur.Y, cur.Z), extType = 0; if (type == Block.custom_block) { extType = p.level.GetExtTile(cur.X, cur.Y, cur.Z); } p.level.Blockchange(p, cur.X, cur.Y, cur.Z, type); while (cur.X != target.X || cur.Z != target.Z) { byte tile = p.level.GetTile(cur.X, cur.Y, cur.Z), extTile = 0; if (tile == Block.custom_block) { extTile = p.level.GetExtTile(cur.X, cur.Y, cur.Z); } if (tile == type) { if (tile != Block.custom_block || (tile == Block.custom_block && extTile == extType)) { p.level.Blockchange(p, cur.X, cur.Y, cur.Z, 0); } } cur.X = (ushort)(cur.X - dirX); cur.Z = (ushort)(cur.Z - dirZ); if (cur.X >= p.level.Width || cur.Z >= p.level.Length) { return; } tile = p.level.GetTile(cur.X, cur.Y, cur.Z); if (tile == Block.mushroom) { p.level.Blockchange(p, cur.X, cur.Y, cur.Z, type, extType); } Thread.Sleep(250); } }
public override void Perform(Vec3S32[] marks, Brush brush, Action <DrawOpBlock> output) { Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); Vec3S32 C = (Min + Max) / 2; int height = Max.Y - Min.Y; for (ushort y = p1.Y; y <= p2.Y; y++) { for (ushort z = p1.Z; z <= p2.Z; z++) { for (ushort x = p1.X; x <= p2.X; x++) { int xx = C.X - x, yy = y - Min.Y, zz = C.Z - z; int curHeight = Invert ? yy : height - yy; if (curHeight == 0) { continue; } double curRadius = Radius * ((double)curHeight / (double)height); int absx = Math.Abs(xx), absz = Math.Abs(zz); if (absx > curRadius || absz > curRadius) { continue; } if (absx < (curRadius - 1) && absz < (curRadius - 1)) { continue; } byte ctile = Level.GetTile(x, y, z); if (ctile != 0) { continue; } output(Place(x, y, z, brush)); } } } }
public override void Perform(Vec3S32[] marks, Brush brush, DrawOpOutput output) { Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); Vec3S32 C = (Min + Max) / 2; int height = Max.Y - Min.Y; for (ushort y = p1.Y; y <= p2.Y; y++) { int yy = y - Min.Y; int curHeight = height - yy; if (curHeight == 0) { continue; } int curRadius = Radius * curHeight / height; int curRadius2 = Radius * (curHeight - 1) / height; for (ushort z = p1.Z; z <= p2.Z; z++) { for (ushort x = p1.X; x <= p2.X; x++) { int dx = C.X - x, dz = C.Z - z; int dist = dx * dx + dz * dz; if (dist > curRadius * curRadius) { continue; } bool layer = curRadius == 0 || !(dist <= (curRadius - 1) * (curRadius - 1) && dist <= (curRadius2) * (curRadius2)); BlockID block = layer ? Block.Grass : Block.StillLava; output(Place(x, y, z, block)); } } } }
static bool MoveGun(WeaponArgs args) { while (true) { args.pos = args.PosAt(args.iterations); args.iterations++; Vec3U16 pos = args.pos; BlockID cur = args.player.level.GetBlock(pos.X, pos.Y, pos.Z); if (cur == Block.Invalid) { return(false); } if (cur != Block.Air && !args.allBlocks.Contains(pos) && HandlesHitBlock(args.player, cur, args.weaponType, pos, true)) { return(false); } args.player.level.Blockchange(pos.X, pos.Y, pos.Z, args.block); args.previous.Add(pos); args.allBlocks.Add(pos); if (HitsPlayer(args, pos)) { return(false); } if (args.iterations > 12 && args.weaponType != WeaponType.Laser) { pos = args.previous[0]; args.previous.RemoveAt(0); args.player.level.Blockchange(pos.X, pos.Y, pos.Z, Block.Air, true); } if (args.weaponType != WeaponType.Laser) { return(true); } } }
public override Level Read(Stream src, string name, bool metadata) { using (Stream gs = new GZipStream(src, CompressionMode.Decompress)) { byte[] header = new byte[16]; Vec3U16 dims = ReadHeader(header, gs); Level lvl = new Level(name, dims.X, dims.Y, dims.Z); lvl.spawnx = BitConverter.ToUInt16(header, 6); lvl.spawnz = BitConverter.ToUInt16(header, 8); lvl.spawny = BitConverter.ToUInt16(header, 10); lvl.rotx = header[12]; lvl.roty = header[13]; // 2 bytes for perbuild and pervisit byte[] blocks = new byte[2 * lvl.blocks.Length]; gs.Read(blocks, 0, blocks.Length); for (int i = 0; i < blocks.Length / 2; ++i) { lvl.blocks[i] = blocks[i * 2]; } return(lvl); } }
public override void Perform(Vec3S32[] marks, Brush brush, Action <DrawOpBlock> output) { Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); Vec3S32 C = (Min + Max) / 2; int height = Max.Y - Min.Y; for (ushort y = p1.Y; y <= p2.Y; y++) { for (ushort z = p1.Z; z <= p2.Z; z++) { for (ushort x = p1.X; x <= p2.X; x++) { int xx = C.X - x, yy = y - Min.Y, zz = C.Z - z; int curHeight = height - yy; if (curHeight == 0) { continue; } double curRadius = Radius * ((double)curHeight / (double)height); int dist = xx * xx + zz * zz; if (dist > curRadius * curRadius) { continue; } byte ctile = Level.GetTile(x, y, z); if (ctile != 0) { continue; } bool layer = dist >= (curRadius - 1) * (curRadius - 1); byte block = layer ? Block.grass : Block.lavastill; output(Place(x, y, z, block, 0)); } } } }
public override void Perform(Vec3U16[] marks, Player p, Level lvl, Brush brush) { Vec3U16 P = marks[0]; int minX = Math.Max(P.X - Radius, 0) - P.X, maxX = Math.Min(P.X + Radius, lvl.Width - 1) - P.X; int minZ = Math.Max(P.Z - Radius, 0) - P.Z, maxZ = Math.Min(P.Z + Radius, lvl.Length - 1) - P.Z; int maxY = Math.Min(P.Y + Height, lvl.Height - 1) - P.Y; for (int yy = 0; yy <= maxY; yy++) { for (int zz = minZ; zz <= maxZ; zz++) { for (int xx = minX; xx <= maxX; xx++) { int cx = (P.X + xx), cy = (P.Y + yy), cz = (P.Z + zz); int curHeight = Height - yy; if (curHeight == 0) { continue; } double curRadius = Radius * ((double)curHeight / (double)Height); int dist = xx * xx + zz * zz; if (dist > curRadius * curRadius) { continue; } byte ctile = lvl.GetTile((ushort)cx, (ushort)cy, (ushort)cz); if (ctile != 0) { continue; } bool layer = dist >= (curRadius - 1) * (curRadius - 1); byte type = layer ? Block.grass : Block.lavastill; PlaceBlock(p, lvl, (ushort)cx, (ushort)cy, (ushort)cz, type, 0); } } } }
public override void Perform(Vec3S32[] marks, Brush brush, DrawOpOutput output) { Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); Vec3S32 C = (Min + Max) / 2; int height = Max.Y - Min.Y; for (ushort y = p1.Y; y <= p2.Y; y++) { int dy = y - Min.Y; int curHeight = Invert ? dy : height - dy; if (curHeight == 0) { continue; } int curRadius = Radius * curHeight / height; int curRadius2 = Radius * (curHeight - 1) / height; for (ushort z = p1.Z; z <= p2.Z; z++) { for (ushort x = p1.X; x <= p2.X; x++) { int dx = C.X - x, dz = C.Z - z; int dist = dx * dx + dz * dz; if (dist > curRadius * curRadius) { continue; } if (dist <= (curRadius - 1) * (curRadius - 1) && dist <= (curRadius2) * (curRadius2)) { continue; } output(Place(x, y, z, brush)); } } } }
public override void Perform(Vec3S32[] marks, Brush brush, DrawOpOutput output) { Vec3U16 p1 = Clamp(Min), p2 = Clamp(Max); Vec3S32 C = (Min + Max) / 2; int height = Max.Y - Min.Y; for (ushort y = p1.Y; y <= p2.Y; y++) { int dy = y - Min.Y; int curHeight = Invert ? dy : height - dy; if (curHeight == 0) { continue; } int curRadius = Radius * curHeight / height; int curRadius2 = Radius * (curHeight - 1) / height; for (ushort z = p1.Z; z <= p2.Z; z++) { for (ushort x = p1.X; x <= p2.X; x++) { int xx = Math.Abs(C.X - x), zz = Math.Abs(C.Z - z); if (xx > curRadius || zz > curRadius) { continue; } if (xx <= (curRadius - 1) && zz <= (curRadius - 1) && xx <= (curRadius2) && zz <= (curRadius2)) { continue; } output(Place(x, y, z, brush)); } } } }
protected static Player GetPlayer(Player p, Vec3U16 pos, bool skipSelf) { Player[] players = PlayerInfo.Online.Items; foreach (Player pl in players) { if (pl.level != p.level) { continue; } if (p == pl && skipSelf) { continue; } if (Math.Abs(pl.Pos.BlockX - pos.X) <= 1 && Math.Abs(pl.Pos.BlockY - pos.Y) <= 1 && Math.Abs(pl.Pos.BlockZ - pos.Z) <= 1) { return(pl); } } return(null); }
public override void Perform(Vec3S32[] marks, Brush brush, Action <DrawOpBlock> output) { /* Courtesy of fCraft's awesome Open-Source'ness :D */ double cx = (Min.X + Max.X) / 2.0, cy = (Min.Y + Max.Y) / 2.0, cz = (Min.Z + Max.Z) / 2.0; double rx = (Max.X - Min.X) / 2.0 + 0.25, ry = (Max.Y - Min.Y) / 2.0 + 0.25, rz = (Max.Z - Min.Z) / 2.0 + 0.25; double rx2 = 1 / (rx * rx), ry2 = 1 / (ry * ry), rz2 = 1 / (rz * rz); Vec3U16 min = Clamp(Min), max = Clamp(Max); for (ushort yy = min.Y; yy <= max.Y; yy++) { for (ushort zz = min.Z; zz <= max.Z; zz++) { for (ushort xx = min.X; xx <= max.X; xx++) { double dx = xx - cx, dy = yy - cy, dz = zz - cz; if ((dx * dx) * rx2 + (dy * dy) * ry2 + (dz * dz) * rz2 <= 1) { output(Place(xx, yy, zz, brush)); } } } } }