diff --git a/MCGalaxy/Commands/CommandParser.cs b/MCGalaxy/Commands/CommandParser.cs
index 6031c468a..0d6b6abb3 100644
--- a/MCGalaxy/Commands/CommandParser.cs
+++ b/MCGalaxy/Commands/CommandParser.cs
@@ -17,6 +17,7 @@
*/
using System;
using MCGalaxy.Blocks;
+using MCGalaxy.Maths;
namespace MCGalaxy.Commands {
@@ -25,7 +26,7 @@ namespace MCGalaxy.Commands {
/// Attempts to parse the given argument as a boolean.
public static bool GetBool(Player p, string input, ref bool result) {
- if (input.CaselessEq("1") || input.CaselessEq("true")
+ if (input.CaselessEq("1") || input.CaselessEq("true")
|| input.CaselessEq("yes") || input.CaselessEq("on")) {
result = true; return true;
}
@@ -106,7 +107,7 @@ namespace MCGalaxy.Commands {
if (value < min || value > max) {
Player.Message(p, "{0} must be between {1} and {2}", argName, min, max);
return false;
- }
+ }
result = value; return true;
}
@@ -129,6 +130,7 @@ namespace MCGalaxy.Commands {
result = (ushort)temp; return true;
}
+
/// Attempts to parse the given argument as a hex color.
public static bool GetHex(Player p, string input, ref ColorDesc col) {
if (input.Length > 0 && input[0] == '#')
@@ -141,6 +143,23 @@ namespace MCGalaxy.Commands {
col = Colors.ParseHex(input); return true;
}
+ internal static bool GetCoords(Player p, string[] args, int argsOffset, ref Vec3S32 P) {
+ return
+ GetCoord(p, args[argsOffset + 0], P.X, "X", out P.X) &&
+ GetCoord(p, args[argsOffset + 1], P.Y, "Y", out P.Y) &&
+ GetCoord(p, args[argsOffset + 2], P.Z, "Z", out P.Z);
+ }
+
+ static bool GetCoord(Player p, string arg, int cur, string axis, out int value) {
+ bool relative = arg[0] == '~';
+ if (relative) arg = arg.Substring(1);
+ value = 0;
+
+ if (!GetInt(p, arg, axis + " coordinate", ref value)) return false;
+ if (relative) value += cur;
+ return true;
+ }
+
/// Attempts to parse the given argument as either a block name or a block ID.
public static bool GetBlock(Player p, string input, out ExtBlock block, bool allowSkip = false) {
diff --git a/MCGalaxy/Commands/building/CmdMark.cs b/MCGalaxy/Commands/building/CmdMark.cs
index e8a8540d5..a5311dde7 100644
--- a/MCGalaxy/Commands/building/CmdMark.cs
+++ b/MCGalaxy/Commands/building/CmdMark.cs
@@ -43,61 +43,49 @@ namespace MCGalaxy.Commands.Building {
return;
}
- // convert player pos to block coords
- Vec3U16 P = ClampPos(p.Pos, p.level);
- if (message.Length > 0 && !ParseCoords(message, p, ref P)) return;
- P = Vec3U16.Clamp(P.X, P.Y, P.Z, p.level);
+ Vec3S32 P = p.Pos.BlockCoords;
+ P.Y = (p.Pos.Y - 32) / 32;
+ if (message.Length > 0 && !ParseCoords(message, p, ref P)) return;
+
+ P.X = Clamp(P.X, p.level.Width);
+ P.Y = Clamp(P.Y, p.level.Height);
+ P.Z = Clamp(P.Z, p.level.Length);
if (p.HasBlockchange) {
- PlaceMark(p, P.X, P.Y, P.Z);
- } else {
- // We only want to activate blocks in the world
- ExtBlock old = p.level.GetBlock(P.X, P.Y, P.Z);
- if (!p.CheckManualChange(old, ExtBlock.Air, true)) return;
-
- HandleDelete handler = p.level.deleteHandlers[old.Index];
- if (handler != null) {
- handler(p, old, P.X, P.Y, P.Z);
- } else {
- Player.Message(p, "Cannot mark, no selection in progress, " +
- "nor could the existing block at the coordinates be activated."); return;
- }
+ PlaceMark(p, P.X, P.Y, P.Z);
+ return;
}
- }
-
- static Vec3U16 ClampPos(Position pos, Level lvl) {
- Vec3S32 p = pos.BlockCoords;
- p.Y--;
- if (p.X < 0) p.X = 0;
- if (p.Y < 0) p.Y = 0;
- if (p.Z < 0) p.Z = 0;
+ Vec3U16 mark = (Vec3U16)P;
+ // We only want to activate blocks in the world
+ ExtBlock old = p.level.GetBlock(mark.X, mark.Y, mark.Z);
+ if (!p.CheckManualChange(old, ExtBlock.Air, true)) return;
- if (p.X >= lvl.Width) p.X = lvl.Width - 1;
- if (p.Y >= lvl.Height) p.Y = lvl.Height - 1;
- if (p.Z >= lvl.Length) p.Z = lvl.Length - 1;
-
- return (Vec3U16)p;
+ HandleDelete handler = p.level.deleteHandlers[old.Index];
+ if (handler != null) {
+ handler(p, old, mark.X, mark.Y, mark.Z);
+ } else {
+ Player.Message(p, "Cannot mark, no selection in progress, " +
+ "nor could the existing block at the coordinates be activated."); return;
+ }
}
- bool ParseCoords(string message, Player p, ref Vec3U16 P) {
+ bool ParseCoords(string message, Player p, ref Vec3S32 P) {
string[] args = message.ToLower().SplitSpaces();
if (args.Length != 3) { Help(p); return false; }
- ushort value;
- for (int i = 0; i < 3; i++) {
- if (args[i] == "x") { P.X = p.lastClick.X;
- } else if (args[i] == "y") { P.Y = p.lastClick.Y;
- } else if (args[i] == "z") { P.Z = p.lastClick.Z;
- } else if (ushort.TryParse(args[i], out value)) {
- if (i == 0) P.X = value;
- else if (i == 1) P.Y = value;
- else P.Z = value;
- } else {
- Player.Message(p, "\"{0}\" was not valid", args[i]); return false;
- }
- }
- return true;
+ // Hacky workaround for backwards compatibility
+ if (args[0].CaselessEq("X")) args[0] = p.lastClick.X.ToString();
+ if (args[1].CaselessEq("Y")) args[1] = p.lastClick.Y.ToString();
+ if (args[2].CaselessEq("Z")) args[2] = p.lastClick.Z.ToString();
+
+ return CommandParser.GetCoords(p, args, 0, ref P);
+ }
+
+ static int Clamp(int value, int axisLen) {
+ if (value < 0) return 0;
+ if (value >= axisLen) return axisLen - 1;
+ return value;
}
static void PlaceMark(Player p, int x, int y, int z) {
@@ -108,9 +96,10 @@ namespace MCGalaxy.Commands.Building {
}
public override void Help(Player p) {
- Player.Message(p, "%T/Mark [x y z] %H- Places a marker for selections. (such as /cuboid)");
- Player.Message(p, " %HIf no xyz is given, marks at where you are standing");
- Player.Message(p, " %He.g. /mark 30 y 20 will mark at (30, last y, 20)");
+ Player.Message(p, "%T/Mark %H- Places a marker for selections, e.g for %T/z");
+ Player.Message(p, "%HUse ~ before a coordinate to mark relative to current position");
+ Player.Message(p, "%HIf is not given, marks at where you are standing");
+ Player.Message(p, " %He.g. /mark 30 y 20 will mark at (30, last y, 20)");
Player.Message(p, " %HNote: If no selection is in progress, activates (e.g. doors) the existing block at those coordinates.");
Player.Message(p, "%T/Mark all %H- Places markers at min and max corners of the map");
}
diff --git a/MCGalaxy/Commands/building/CmdPlace.cs b/MCGalaxy/Commands/building/CmdPlace.cs
index a7181ac84..99d8dabc9 100644
--- a/MCGalaxy/Commands/building/CmdPlace.cs
+++ b/MCGalaxy/Commands/building/CmdPlace.cs
@@ -16,6 +16,7 @@
permissions and limitations under the Licenses.
*/
using System;
+using MCGalaxy.Maths;
namespace MCGalaxy.Commands.Building {
public sealed class CmdPlace : Command {
@@ -27,7 +28,8 @@ namespace MCGalaxy.Commands.Building {
public override void Use(Player p, string message) {
ExtBlock block = p.GetHeldBlock();
- int x = p.Pos.BlockX, y = (p.Pos.Y - 32) / 32, z = p.Pos.BlockZ;
+ Vec3S32 P = p.Pos.BlockCoords;
+ P.Y = (p.Pos.Y - 32) / 32;
string[] parts = message.SplitSpaces();
switch (parts.Length) {
@@ -36,30 +38,25 @@ namespace MCGalaxy.Commands.Building {
if (!CommandParser.GetBlock(p, parts[0], out block)) return;
break;
case 3:
- if (!CommandParser.GetInt(p, parts[0], "X", ref x)) return;
- if (!CommandParser.GetInt(p, parts[1], "Y", ref y)) return;
- if (!CommandParser.GetInt(p, parts[2], "Z", ref z)) return;
+ if (!CommandParser.GetCoords(p, parts, 0, ref P)) return;
break;
case 4:
if (!CommandParser.GetBlock(p, parts[0], out block)) return;
- if (!CommandParser.GetInt(p, parts[1], "X", ref x)) return;
- if (!CommandParser.GetInt(p, parts[2], "Y", ref y)) return;
- if (!CommandParser.GetInt(p, parts[3], "Z", ref z)) return;
+ if (!CommandParser.GetCoords(p, parts, 1, ref P)) return;
break;
default:
Help(p); return;
}
- if (!CommandParser.IsBlockAllowed(p, "place", block)) return;
+ if (!CommandParser.IsBlockAllowed(p, "place", block)) return;
+ P.X = Clamp(P.X, p.level.Width);
+ P.Y = Clamp(P.Y, p.level.Height);
+ P.Z = Clamp(P.Z, p.level.Length);
- x = Clamp(x, p.level.Width);
- y = Clamp(y, p.level.Height);
- z = Clamp(z, p.level.Length);
-
- p.level.UpdateBlock(p, (ushort)x, (ushort)y, (ushort)z, block);
+ p.level.UpdateBlock(p, (ushort)P.X, (ushort)P.Y, (ushort)P.Z, block);
string blockName = p.level.BlockName(block);
if (!p.Ignores.DrawOutput) {
- Player.Message(p, "{3} block was placed at ({0}, {1}, {2}).", x, y, z, blockName);
+ Player.Message(p, "{3} block was placed at ({0}, {1}, {2}).", P.X, P.Y, P.Z, blockName);
}
}
@@ -74,6 +71,7 @@ namespace MCGalaxy.Commands.Building {
Player.Message(p, "%HPlaces block at your feet.");
Player.Message(p, "%T/Place [x y z]");
Player.Message(p, "%HPlaces block at [x y z]");
+ Player.Message(p, "%HUse ~ before a coord to place relative to current position");
}
}
}
diff --git a/MCGalaxy/Commands/other/CmdTp.cs b/MCGalaxy/Commands/other/CmdTp.cs
index 5d061f01d..b8117215d 100644
--- a/MCGalaxy/Commands/other/CmdTp.cs
+++ b/MCGalaxy/Commands/other/CmdTp.cs
@@ -16,6 +16,7 @@
permissions and limitations under the Licenses.
*/
using MCGalaxy.Games;
+using MCGalaxy.Maths;
namespace MCGalaxy.Commands.Misc {
public sealed class CmdTp : Command {
@@ -67,23 +68,11 @@ namespace MCGalaxy.Commands.Misc {
}
static void TeleportCoords(Player p, string[] args) {
- int x, y, z;
- if (!ParseCoord(p, args[0], p.Pos.X, "X", out x)) return;
- if (!ParseCoord(p, args[1], p.Pos.Y - Entities.CharacterHeight, "Y", out y)) return;
- if (!ParseCoord(p, args[2], p.Pos.Z, "Z", out z)) return;
+ Vec3S32 P = p.Pos.BlockFeetCoords;
+ if (!CommandParser.GetCoords(p, args, 0, ref P)) return;
p.PreTeleportPos = p.Pos;
- PlayerActions.MoveCoords(p, x, y, z, p.Rot.RotY, p.Rot.HeadX);
- }
-
- static bool ParseCoord(Player p, string arg, int cur, string axis, out int value) {
- bool relative = arg[0] == '~';
- if (relative) arg = arg.Substring(1);
- value = 0;
-
- if (!CommandParser.GetInt(p, arg, axis + " coordinate", ref value)) return false;
- if (relative) value += (cur / 32);
- return true;
+ PlayerActions.MoveCoords(p, P.X, P.Y, P.Z, p.Rot.RotY, p.Rot.HeadX);
}
static bool CheckPlayer(Player p, Player target) {
diff --git a/MCGalaxy/CorePlugin/CorePlugin.cs b/MCGalaxy/CorePlugin/CorePlugin.cs
index 88aae2339..99ddcb257 100644
--- a/MCGalaxy/CorePlugin/CorePlugin.cs
+++ b/MCGalaxy/CorePlugin/CorePlugin.cs
@@ -15,15 +15,12 @@
or implied. See the Licenses for the specific language governing
permissions and limitations under the Licenses.
*/
-using System;
-using System.Collections.Generic;
-using System.IO;
-using MCGalaxy.Eco;
-using MCGalaxy.Events;
-using MCGalaxy.Events.EconomyEvents;
-using MCGalaxy.Events.GroupEvents;
-using MCGalaxy.Events.PlayerEvents;
-using MCGalaxy.Tasks;
+using System;
+using MCGalaxy.Events;
+using MCGalaxy.Events.EconomyEvents;
+using MCGalaxy.Events.GroupEvents;
+using MCGalaxy.Events.PlayerEvents;
+using MCGalaxy.Tasks;
namespace MCGalaxy.Core {