Add a real /sphere command.

This commit is contained in:
UnknownShadow200 2016-05-19 21:42:08 +10:00
parent 783cb226dc
commit 5c3cb9d16e
9 changed files with 120 additions and 34 deletions

View File

@ -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) {

View File

@ -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;

View File

@ -27,6 +27,7 @@ namespace MCGalaxy.Commands {
public override string name { get { return "line"; } }
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;

View File

@ -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<BrushArgs, Brush> 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] <mode>");
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");
}
}
}

View File

@ -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) {

View File

@ -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;

View File

@ -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; } }
}

View File

@ -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;

View File

@ -143,6 +143,7 @@
<Compile Include="Commands\building\CmdRainbow.cs" />
<Compile Include="Commands\building\CmdRedo.cs" />
<Compile Include="Commands\building\CmdReplaceBrush.cs" />
<Compile Include="Commands\building\CmdSphere.cs" />
<Compile Include="Commands\building\CmdTriangle.cs" />
<Compile Include="Commands\building\ReplaceCmd.cs" />
<Compile Include="Commands\building\CmdRestartPhysics.cs" />