From 0da31735e5ca6a52b251c173afd2789cc003b76b Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Mon, 4 Sep 2017 23:12:55 +1000 Subject: [PATCH] Add relative coords in /place and /mark. --- MCGalaxy/Commands/CommandParser.cs | 23 ++++++- MCGalaxy/Commands/building/CmdMark.cs | 85 +++++++++++--------------- MCGalaxy/Commands/building/CmdPlace.cs | 26 ++++---- MCGalaxy/Commands/other/CmdTp.cs | 19 ++---- MCGalaxy/CorePlugin/CorePlugin.cs | 15 ++--- 5 files changed, 80 insertions(+), 88 deletions(-) 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 {