Add relative coords in /place and /mark.

This commit is contained in:
UnknownShadow200 2017-09-04 23:12:55 +10:00
parent c81ec5af00
commit 0da31735e5
5 changed files with 80 additions and 88 deletions

View File

@ -17,6 +17,7 @@
*/
using System;
using MCGalaxy.Blocks;
using MCGalaxy.Maths;
namespace MCGalaxy.Commands {
@ -25,7 +26,7 @@ namespace MCGalaxy.Commands {
/// <summary> Attempts to parse the given argument as a boolean. </summary>
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;
}
/// <summary> Attempts to parse the given argument as a hex color. </summary>
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;
}
/// <summary> Attempts to parse the given argument as either a block name or a block ID. </summary>
public static bool GetBlock(Player p, string input, out ExtBlock block, bool allowSkip = false) {

View File

@ -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 <x y z> %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 <x y z> 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");
}

View File

@ -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 <block> [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");
}
}
}

View File

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

View File

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