From d972b0de2f84dc4dcb3e073242e05c980108a1c5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 2 Sep 2025 15:10:44 +0000 Subject: [PATCH] Add relative positioning support to execute command using ~ syntax Co-authored-by: aronwk-aaron <26027722+aronwk-aaron@users.noreply.github.com> --- .../SlashCommands/DEVGMCommands.cpp | 45 ++++++++++++++----- docs/Commands.md | 2 +- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/dGame/dUtilities/SlashCommands/DEVGMCommands.cpp b/dGame/dUtilities/SlashCommands/DEVGMCommands.cpp index 14dd5164..23f897b5 100644 --- a/dGame/dUtilities/SlashCommands/DEVGMCommands.cpp +++ b/dGame/dUtilities/SlashCommands/DEVGMCommands.cpp @@ -1671,10 +1671,11 @@ namespace DEVGMCommands { ChatPackets::SendSystemMessage(sysAddr, u"Subcommands:"); ChatPackets::SendSystemMessage(sysAddr, u" as - Execute as different player"); ChatPackets::SendSystemMessage(sysAddr, u" at - Execute from player's position"); - ChatPackets::SendSystemMessage(sysAddr, u" positioned - Execute from coordinates"); + ChatPackets::SendSystemMessage(sysAddr, u" positioned - Execute from coordinates (absolute or relative with ~)"); ChatPackets::SendSystemMessage(sysAddr, u"Examples:"); ChatPackets::SendSystemMessage(sysAddr, u" /execute as Player1 run pos"); ChatPackets::SendSystemMessage(sysAddr, u" /execute at Player2 positioned 100 200 300 run spawn 1234"); + ChatPackets::SendSystemMessage(sysAddr, u" /execute positioned ~5 ~10 ~ run spawn 1234"); return; } @@ -1739,20 +1740,44 @@ namespace DEVGMCommands { } try { - float x = std::stof(splitArgs[i + 1]); - float y = std::stof(splitArgs[i + 2]); - float z = std::stof(splitArgs[i + 3]); + // Parse coordinates with support for relative positioning (~) + auto parseCoordinate = [&](const std::string& coord, float currentValue) -> float { + if (coord.empty()) { + throw std::invalid_argument("Empty coordinate"); + } + + if (coord[0] == '~') { + // Relative coordinate + if (coord.length() == 1) { + // Just "~" means current position (offset 0) + return currentValue; + } else { + // "~" means current position + offset + std::string offsetStr = coord.substr(1); + float offset = std::stof(offsetStr); + if (!std::isfinite(offset)) { + throw std::invalid_argument("Invalid offset"); + } + return currentValue + offset; + } + } else { + // Absolute coordinate + float absolute = std::stof(coord); + if (!std::isfinite(absolute)) { + throw std::invalid_argument("Invalid absolute coordinate"); + } + return absolute; + } + }; - // Basic coordinate validation - if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(z)) { - ChatPackets::SendSystemMessage(sysAddr, u"Error: Coordinates must be finite numbers"); - return; - } + float x = parseCoordinate(splitArgs[i + 1], execPosition.x); + float y = parseCoordinate(splitArgs[i + 2], execPosition.y); + float z = parseCoordinate(splitArgs[i + 3], execPosition.z); execPosition = NiPoint3(x, y, z); positionOverridden = true; } catch (const std::exception&) { - ChatPackets::SendSystemMessage(sysAddr, u"Error: Invalid coordinates for 'positioned'. Use numeric values."); + ChatPackets::SendSystemMessage(sysAddr, u"Error: Invalid coordinates for 'positioned'. Use numeric values or relative coordinates with ~."); return; } diff --git a/docs/Commands.md b/docs/Commands.md index b0110668..54d5e531 100644 --- a/docs/Commands.md +++ b/docs/Commands.md @@ -116,7 +116,7 @@ These commands are primarily for development and testing. The usage of many of t |setrewardcode|`/setrewardcode `|Sets the rewardcode for the account you are logged into if it's a valid rewardcode, See cdclient table `RewardCodes`|8| |barfight|`/barfight start`|Starts a barfight (turns everyones pvp on)|8| |despawn|`/despawn `|Despawns the entity objectID IF it was spawned in through a slash command.|8| -|execute|`/execute ... run `|Execute commands with modified context (Minecraft-style). Subcommands: `as ` (execute as different player), `at ` (execute from player's position), `positioned ` (execute from coordinates). Example: `/execute as Player1 run pos`|8| +|execute|`/execute ... run `|Execute commands with modified context (Minecraft-style). Subcommands: `as ` (execute as different player), `at ` (execute from player's position), `positioned ` (execute from coordinates - supports absolute coordinates like `100 200 300` or relative coordinates like `~5 ~10 ~` where `~` means current position). Example: `/execute as Player1 run pos`, `/execute positioned ~5 ~ ~-3 run spawn 1234`|8| |crash|`/crash`|Crashes the server.|9| |rollloot|`/rollloot `|Given a `loot matrix index`, look for `item id` in that matrix `amount` times and print to the chat box statistics of rolling that loot matrix.|9| |castskill|`/castskill `|Casts the skill as the player|9|