diff --git a/Commands/building/CmdCuboid.cs b/Commands/building/CmdCuboid.cs index 1eb8674a0..fe223e534 100644 --- a/Commands/building/CmdCuboid.cs +++ b/Commands/building/CmdCuboid.cs @@ -27,9 +27,9 @@ namespace MCGalaxy.Commands public override string name { get { return "cuboid"; } } public override string shortcut { get { return "z"; } } public override CommandAlias[] Aliases { - get { return new[] { new CommandAlias("cw", "wire"), - new CommandAlias("ch", "hollow"), new CommandAlias("walls", "walls"), - new CommandAlias("box"), new CommandAlias("hbox", "hollow") }; } + get { return new[] { new CommandAlias("cw", null, "wire"), + new CommandAlias("ch", null, "hollow"), new CommandAlias("walls", null, "walls"), + new CommandAlias("box"), new CommandAlias("hbox", null, "hollow") }; } } protected override void Blockchange2(Player p, ushort x, ushort y, ushort z, byte type, byte extType) { diff --git a/Commands/building/CmdDraw.cs b/Commands/building/CmdDraw.cs index 453e68dba..e83d3bae1 100644 --- a/Commands/building/CmdDraw.cs +++ b/Commands/building/CmdDraw.cs @@ -73,22 +73,22 @@ namespace MCGalaxy.Commands { default: Help(p); return; } + ushort radius = 0, height = 0; string[] args = cpos.message.Split(' '); - if ((op.UsesHeight && !CheckTwoArgs(p, op, args)) || - (!op.UsesHeight && !CheckOneArg(p, op, args))) return; + if ((op.UsesHeight && !CheckTwoArgs(p, ref radius, ref height, args)) || + (!op.UsesHeight && !CheckOneArg(p, ref radius, args))) return; int brushOffset = op.UsesHeight ? 3 : 2; Brush brush = GetBrush(p, cpos, brushOffset); if (brush == null) return; Vec3S32[] marks = { - new Vec3S32(x - op.Radius, y, z - op.Radius), - new Vec3S32(x + op.Radius, y, z + op.Radius) }; + new Vec3S32(x - radius, y, z - radius), + new Vec3S32(x + radius, y, z + radius) }; if (op.UsesHeight) { - marks[1].Y += op.Height; + marks[1].Y += height; } else { - marks[0].Y -= op.Radius; - marks[1].Y += op.Radius; + marks[0].Y -= radius; marks[1].Y += radius; } if (!DrawOp.DoDrawOp(op, brush, p, marks)) @@ -99,18 +99,18 @@ namespace MCGalaxy.Commands { protected override void Blockchange2(Player p, ushort x, ushort y, ushort z, byte type, byte extType) { } - bool CheckTwoArgs(Player p, AdvDrawOp op, string[] parts) { + bool CheckTwoArgs(Player p, ref ushort radius, ref ushort height, string[] parts) { if (parts.Length < 3) { Help(p); return false; } - if (!ushort.TryParse(parts[parts.Length - 3], out op.Height) || op.Height > 2000 || - !ushort.TryParse(parts[parts.Length - 2], out op.Radius) || op.Radius > 2000) { + if (!ushort.TryParse(parts[parts.Length - 3], out height) || height > 2000 || + !ushort.TryParse(parts[parts.Length - 2], out radius) || radius > 2000) { Player.Message(p, "Radius and height must be positive integers less than 2000."); return false; } return true; } - bool CheckOneArg(Player p, AdvDrawOp op, string[] parts) { + bool CheckOneArg(Player p, ref ushort radius, string[] parts) { if (parts.Length < 2) { Help(p); return false; } - if (!ushort.TryParse(parts[parts.Length - 2], out op.Radius) || op.Radius > 2000) { + if (!ushort.TryParse(parts[parts.Length - 2], out radius) || radius > 2000) { Player.Message(p, "Radius must be a positive integer less than 2000."); return false; } return true; diff --git a/Commands/building/CmdLine.cs b/Commands/building/CmdLine.cs index 1124e0f4f..12f8f9fbb 100644 --- a/Commands/building/CmdLine.cs +++ b/Commands/building/CmdLine.cs @@ -26,7 +26,8 @@ namespace MCGalaxy.Commands { public sealed class CmdLine : DrawCmd { public override string name { get { return "line"; } } - public override string shortcut { get { return "l"; } } + public override string shortcut { get { return "l"; } } + protected override string PlaceMessage { get { return "Place two blocks to determine the endpoints."; } } protected override DrawMode ParseMode(string msg) { if (msg == "normal") return DrawMode.solid; diff --git a/Commands/building/CmdSphere.cs b/Commands/building/CmdSphere.cs new file mode 100644 index 000000000..b4f3447d9 --- /dev/null +++ b/Commands/building/CmdSphere.cs @@ -0,0 +1,79 @@ +/* + Copyright 2015 MCGalaxy + + Dual-licensed under the Educational Community License, Version 2.0 and + the GNU General Public License, Version 3 (the "Licenses"); you may + not use this file except in compliance with the Licenses. You may + obtain a copy of the Licenses at + + http://www.opensource.org/licenses/ecl2.php + http://www.gnu.org/licenses/gpl-3.0.html + + Unless required by applicable law or agreed to in writing, + software distributed under the Licenses are distributed on an "AS IS" + BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + or implied. See the Licenses for the specific language governing + permissions and limitations under the Licenses. + */ +using System; +using System.Collections.Generic; +using MCGalaxy.Drawing; +using MCGalaxy.Drawing.Ops; +using MCGalaxy.Drawing.Brushes; + +namespace MCGalaxy.Commands { + public sealed class CmdSphere : DrawCmd { + + public override string name { get { return "sphere"; } } + public override string shortcut { get { return "sp"; } } + public override LevelPermission defaultRank { get { return LevelPermission.AdvBuilder; } } + public override CommandAlias[] Aliases { + get { return new[] { new CommandAlias("sphereh", null, "hollow"), new CommandAlias("sph", null, "hollow") }; } + } + protected override string PlaceMessage { get { return "Place a block for the centre, then another for the radius."; } } + + protected override DrawMode ParseMode(string msg) { + if (msg == "solid") return DrawMode.solid; + else if (msg == "hollow") return DrawMode.hollow; + return DrawMode.normal; + } + + protected override void Blockchange2(Player p, ushort x, ushort y, ushort z, byte type, byte extType) { + RevertAndClearState(p, x, y, z); + CatchPos cpos = (CatchPos)p.blockchangeObject; + GetRealBlock(type, extType, p, ref cpos); + + int dx = cpos.x - x, dy = cpos.y - y, dz = cpos.z - z; + int radius = (int)Math.Sqrt(dx * dx + dy * dy + dz * dz); + Vec3S32[] marks = { new Vec3S32(cpos.x - radius, cpos.y - radius, cpos.z - radius), + new Vec3S32(cpos.x + radius, cpos.y + radius, cpos.z + radius) }; + + DrawOp op = null; + Func constructor = null; + switch (cpos.mode) { + case DrawMode.solid: + op = new AdvSphereDrawOp(); + constructor = SolidBrush.Process; break; + case DrawMode.hollow: + op = new AdvHollowSphereDrawOp(); break; + default: + op = new AdvSphereDrawOp(); break; + } + int brushOffset = cpos.mode == DrawMode.normal ? 0 : 1; + Brush brush = GetBrush(p, cpos, brushOffset, constructor); + if (brush == null) return; + + if (!DrawOp.DoDrawOp(op, brush, p, marks)) + return; + if (p.staticCommands) + p.Blockchange += new Player.BlockchangeEventHandler(Blockchange1); + } + + public override void Help(Player p) { + Player.Message(p, "%T/sphere [brush args] "); + Player.Message(p, "%HCreates a sphere, using the first point as the centre, and the second point as the radius."); + Player.Message(p, " %HFor help about brushes, type %T/help brush%H."); + Player.Message(p, " %HModes: &fsolid/hollow"); + } + } +} diff --git a/Commands/building/CmdSpheroid.cs b/Commands/building/CmdSpheroid.cs index 878c81bee..de1cf8690 100644 --- a/Commands/building/CmdSpheroid.cs +++ b/Commands/building/CmdSpheroid.cs @@ -27,8 +27,7 @@ namespace MCGalaxy.Commands { public override string name { get { return "spheroid"; } } public override string shortcut { get { return "e"; } } public override CommandAlias[] Aliases { - get { return new[] { new CommandAlias("sphere"), new CommandAlias("eh", "hollow"), - new CommandAlias("cylinder", "vertical") }; } + get { return new[] { new CommandAlias("eh", null, "hollow"), new CommandAlias("cylinder", null, "vertical") }; } } protected override void Blockchange2(Player p, ushort x, ushort y, ushort z, byte type, byte extType) { diff --git a/Drawing/DrawOps/AdvConeDrawOps.cs b/Drawing/DrawOps/AdvConeDrawOps.cs index 02add22aa..2ce4023cc 100644 --- a/Drawing/DrawOps/AdvConeDrawOps.cs +++ b/Drawing/DrawOps/AdvConeDrawOps.cs @@ -30,23 +30,24 @@ namespace MCGalaxy.Drawing.Ops { public override string Name { get { return "Adv Cone"; } } public override long GetBlocksAffected(Level lvl, Vec3S32[] marks) { - long R = Radius, H = Height; + long R = Radius, H = Max.Y - Min.Y; return (long)(Math.PI / 3 * (R * R * H)); } public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { 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; + int curHeight = Invert ? yy : height - yy; if (curHeight == 0) continue; - double curRadius = Radius * ((double)curHeight / (double)Height); + double curRadius = Radius * ((double)curHeight / (double)height); int dist = xx * xx + zz * zz; if (dist > curRadius * curRadius) continue; @@ -62,7 +63,7 @@ namespace MCGalaxy.Drawing.Ops { public override string Name { get { return "Adv Hollow Cone"; } } public override long GetBlocksAffected(Level lvl, Vec3S32[] marks) { - long R = Radius, H = Height; + long R = Radius, H = Max.Y - Min.Y; double outer = (int)(Math.PI / 3 * (R * R * H)); double inner = (int)(Math.PI / 3 * ((R - 1) * (R - 1) * (H - 1))); return (long)(outer - inner); @@ -71,16 +72,17 @@ namespace MCGalaxy.Drawing.Ops { public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { 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; + int curHeight = Invert ? yy : height - yy; if (curHeight == 0) continue; - double curRadius = Radius * ((double)curHeight / (double)Height); + double curRadius = Radius * ((double)curHeight / (double)height); int dist = xx * xx + zz * zz; if (dist > curRadius * curRadius || dist < (curRadius - 1) * (curRadius - 1)) continue; @@ -97,23 +99,24 @@ namespace MCGalaxy.Drawing.Ops { public override string Name { get { return "Adv Volcano"; } } public override long GetBlocksAffected(Level lvl, Vec3S32[] marks) { - long R = Radius, H = Height; + long R = Radius, H = Max.Y - Min.Y; return (long)(Math.PI / 3 * (R * R * H)); } public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { 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; + int curHeight = height - yy; if (curHeight == 0) continue; - double curRadius = Radius * ((double)curHeight / (double)Height); + double curRadius = Radius * ((double)curHeight / (double)height); int dist = xx * xx + zz * zz; if (dist > curRadius * curRadius) continue; diff --git a/Drawing/DrawOps/AdvDrawOps.cs b/Drawing/DrawOps/AdvDrawOps.cs index 6b0e79290..1dbfcec1e 100644 --- a/Drawing/DrawOps/AdvDrawOps.cs +++ b/Drawing/DrawOps/AdvDrawOps.cs @@ -26,7 +26,8 @@ using MCGalaxy.Drawing.Brushes; namespace MCGalaxy.Drawing.Ops { public abstract class AdvDrawOp : DrawOp { - public ushort Radius, Height; + public int Radius { get { return (Max.X - Min.X) / 2; } } + public bool Invert; public virtual bool UsesHeight { get { return true; } } } diff --git a/Drawing/DrawOps/AdvPyramidDrawOps.cs b/Drawing/DrawOps/AdvPyramidDrawOps.cs index 3fb438123..f495e1fd7 100644 --- a/Drawing/DrawOps/AdvPyramidDrawOps.cs +++ b/Drawing/DrawOps/AdvPyramidDrawOps.cs @@ -30,7 +30,7 @@ namespace MCGalaxy.Drawing.Ops { public override string Name { get { return "Adv Pyramid"; } } public override long GetBlocksAffected(Level lvl, Vec3S32[] marks) { - long R = Radius, H = Height; + long R = Radius, H = Max.Y - Min.Y; return (R * R * H) / 3; } @@ -42,11 +42,12 @@ namespace MCGalaxy.Drawing.Ops { for (ushort z = p1.Z; z <= p2.Z; z++) for (ushort x = p1.X; x <= p2.X; x++) { + int height = Max.Y - Min.Y; int xx = C.X - x, yy = y - Min.Y, zz = C.Z - z; - int curHeight = Invert ? yy : Height - yy; + int curHeight = Invert ? yy : height - yy; if (curHeight == 0) continue; - double curRadius = Radius * ((double)curHeight / (double)Height); + double curRadius = Radius * ((double)curHeight / (double)height); if (Math.Abs(xx) > curRadius || Math.Abs(zz) > curRadius) continue; byte ctile = lvl.GetTile(x, y, z); @@ -61,7 +62,7 @@ namespace MCGalaxy.Drawing.Ops { public override string Name { get { return "Adv Hollow Pyramid"; } } public override long GetBlocksAffected(Level lvl, Vec3S32[] marks) { - long R = Radius, H = Height; + long R = Radius, H = Max.Y - Min.Y; long outer = (R * R * H) / 3; long inner = ((R - 1) * (R - 1) * (H - 1)) / 3; return outer - inner; @@ -70,16 +71,17 @@ namespace MCGalaxy.Drawing.Ops { public override void Perform(Vec3S32[] marks, Player p, Level lvl, Brush brush) { 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; + int curHeight = Invert ? yy : height - yy; if (curHeight == 0) continue; - double curRadius = Radius * ((double)curHeight / (double)Height); + 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; diff --git a/MCGalaxy_.csproj b/MCGalaxy_.csproj index 25378cd6e..06077bcd7 100644 --- a/MCGalaxy_.csproj +++ b/MCGalaxy_.csproj @@ -143,6 +143,7 @@ +