From 09dd74843c1e67be954f5ec2dbbfca5443931fff Mon Sep 17 00:00:00 2001 From: Aaron Kimbrell Date: Mon, 26 Oct 2026 20:33:41 -0500 Subject: [PATCH] chore: remove the scene point spawn commands and send /getadjacentscenes as one message The spawn commands were only for testing. /getscene and /getadjacentscenes stay. Co-Authored-By: Claude Opus 5.5 --- dGame/dUtilities/SlashCommandHandler.cpp | 17 -- .../SlashCommands/DEVGMCommands.cpp | 184 +----------------- .../dUtilities/SlashCommands/DEVGMCommands.h | 2 - docs/Commands.md | 2 - .../dZoneManagerTests/ZoneSceneTests.cpp | 31 +-- 5 files changed, 12 insertions(+), 224 deletions(-) diff --git a/dGame/dUtilities/SlashCommandHandler.cpp b/dGame/dUtilities/SlashCommandHandler.cpp index 1d9eda2e0..8559835a2 100644 --- a/dGame/dUtilities/SlashCommandHandler.cpp +++ b/dGame/dUtilities/SlashCommandHandler.cpp @@ -835,23 +835,6 @@ void SlashCommandHandler::Startup() { }; RegisterCommand(GetAdjacentScenesCommand); - Command SpawnScenePointsCommand{ - .help = "Spawn bricks at points across your current scene", - .info = "Spawns bricks across the player's current scene using terrain scene map data, one every heightmap points (default 8). Usage: /spawnscenepoints (step)", - .aliases = { "spawnscenepoints" }, - .handle = DEVGMCommands::SpawnScenePoints, - .requiredLevel = eGameMasterLevel::DEVELOPER - }; - RegisterCommand(SpawnScenePointsCommand); - - Command SpawnAllScenePointsCommand{ - .help = "Spawn bricks across all scenes in the zone", - .info = "Spawns bricks across every scene in the zone, one every heightmap points (default 8; 1 = every point, a massive number of entities). Usage: /spawnallscenepoints (step)", - .aliases = { "spawnallscenepoints", "spawnallscenes" }, - .handle = DEVGMCommands::SpawnAllScenePoints, - .requiredLevel = eGameMasterLevel::DEVELOPER - }; - RegisterCommand(SpawnAllScenePointsCommand); // Register Greater Than Zero Commands diff --git a/dGame/dUtilities/SlashCommands/DEVGMCommands.cpp b/dGame/dUtilities/SlashCommands/DEVGMCommands.cpp index ecf9fcecf..91e9e1255 100644 --- a/dGame/dUtilities/SlashCommands/DEVGMCommands.cpp +++ b/dGame/dUtilities/SlashCommands/DEVGMCommands.cpp @@ -1,6 +1,5 @@ #include "DEVGMCommands.h" -#include #include // Classes @@ -25,8 +24,6 @@ // Database #include "Database.h" -#include "CDClientManager.h" -#include "CDBrickIDTableTable.h" #include "CDObjectsTable.h" #include "CDRewardCodesTable.h" #include "CDLootMatrixTable.h" @@ -1894,19 +1891,6 @@ namespace DEVGMCommands { } } - // A different LEGO brick per scene so the scenes can be told apart, from the BrickIDTable (every brick's LOT) - static LOT GetScenePointLot(uint8_t sceneID) { - static const std::vector brickLots = [] { - std::vector lots; - for (const auto& brick : CDClientManager::GetTable()->Query([](const CDBrickIDTable&) { return true; })) { - lots.push_back(brick.NDObjectID); - } - std::ranges::sort(lots); - return lots; - }(); - return brickLots.empty() ? LOT_NULL : brickLots[sceneID % brickLots.size()]; - } - void GetScene(Entity* entity, const SystemAddress& sysAddr, const std::string args) { const auto position = entity->GetPosition(); @@ -1964,171 +1948,23 @@ namespace DEVGMCommands { // Get adjacent scenes const auto adjacentSceneIDs = Game::zoneManager->GetAdjacentScenes(sceneID); - if (adjacentSceneIDs.empty()) { - std::ostringstream feedback; - feedback << "Current Scene: " << sceneID.GetSceneID() << " (" << currentSceneName << ")"; - feedback << " - No adjacent scenes found."; - ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(feedback.str())); - return; - } - - // Build the feedback message with current scene std::ostringstream feedback; feedback << "Current Scene: " << sceneID.GetSceneID() << " (" << currentSceneName << ")"; - ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(feedback.str())); - - // List all adjacent scenes - feedback.str(""); - feedback << "Adjacent Scenes (" << adjacentSceneIDs.size() << "):"; - ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(feedback.str())); - - for (const auto& adjSceneID : adjacentSceneIDs) { - feedback.str(""); - feedback << " - Scene ID: " << adjSceneID.GetSceneID(); - feedback << " (Layer: " << adjSceneID.GetLayerID() << ")"; - - // Get the scene name if available - const auto* sceneRef = zone->GetScene(adjSceneID); - if (sceneRef && !sceneRef->name.empty()) { - feedback << " - " << sceneRef->name; - } - - ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(feedback.str())); - } - } + if (adjacentSceneIDs.empty()) { + feedback << " - No adjacent scenes found."; + } else { + feedback << "\nAdjacent Scenes (" << adjacentSceneIDs.size() << "):"; + for (const auto& adjSceneID : adjacentSceneIDs) { + feedback << "\n - Scene ID: " << adjSceneID.GetSceneID() << " (Layer: " << adjSceneID.GetLayerID() << ")"; - void SpawnScenePoints(Entity* entity, const SystemAddress& sysAddr, const std::string args) { - // Spawn one brick every heightmap points (default 8) - const auto parsedStep = GeneralUtils::TryParse(args); - const uint32_t step = parsedStep && *parsedStep > 0 ? *parsedStep : 8; - - // Get player's current position and scene - const auto position = entity->GetPosition(); - const auto currentSceneID = Game::zoneManager->GetSceneIDFromPosition(position); - if (currentSceneID == LWOSCENEID_INVALID) { - ChatPackets::SendSystemMessage(sysAddr, u"No scene found at current position."); - return; - } - - // Get the zone - const auto* zone = Game::zoneManager->GetZone(); - if (!zone) { - ChatPackets::SendSystemMessage(sysAddr, u"No zone loaded."); - return; - } - - // Get the Raw terrain data - const auto& raw = zone->GetZoneRaw(); - if (raw.chunks.empty()) { - ChatPackets::SendSystemMessage(sysAddr, u"Zone does not have valid terrain data."); - return; - } - - uint32_t spawnedCount = 0; - - for (const auto& chunk : raw.chunks) { - if (!chunk.IsValidForSceneLookup()) continue; - - for (uint32_t i = 0; i < chunk.width; i += step) { - for (uint32_t j = 0; j < chunk.height; j += step) { - const uint8_t sceneID = chunk.GetSceneIDAtGrid(i, j); - if (sceneID != currentSceneID.GetSceneID()) continue; - - EntityInfo info; - info.lot = GetScenePointLot(sceneID); - info.pos = chunk.GridToWorldPos(i, j); - info.rot = QuatUtils::IDENTITY; - info.spawner = nullptr; - info.spawnerID = entity->GetObjectID(); - info.spawnerNodeID = 0; - info.settings.Insert(u"SpawnedFromSlashCommand", true); - - Entity* newEntity = Game::entityManager->CreateEntity(info, nullptr); - if (newEntity != nullptr) { - Game::entityManager->ConstructEntity(newEntity); - spawnedCount++; - } + // Get the scene name if available + const auto* sceneRef = zone->GetScene(adjSceneID); + if (sceneRef && !sceneRef->name.empty()) { + feedback << " - " << sceneRef->name; } } } - if (spawnedCount == 0) { - std::ostringstream feedback; - feedback << "No spawn points found in current scene (ID: " << currentSceneID.GetSceneID() << ")."; - ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(feedback.str())); - return; - } - - // Send feedback - const auto* sceneRef = zone->GetScene(currentSceneID); - const std::string sceneName = sceneRef ? sceneRef->name : "Unknown"; - std::ostringstream feedback; - feedback << "Spawned " << spawnedCount << " points (LOT " << GetScenePointLot(currentSceneID.GetSceneID()) << ") in scene " - << currentSceneID.GetSceneID() << " (" << sceneName << ")."; - ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(feedback.str())); - } - - void SpawnAllScenePoints(Entity* entity, const SystemAddress& sysAddr, const std::string args) { - // Spawn one brick every heightmap points (default 8) - const auto parsedStep = GeneralUtils::TryParse(args); - const uint32_t step = parsedStep && *parsedStep > 0 ? *parsedStep : 8; - - // Get the zone - const auto* zone = Game::zoneManager->GetZone(); - if (!zone) { - ChatPackets::SendSystemMessage(sysAddr, u"No zone loaded."); - return; - } - - // Get the Raw terrain data - const auto& raw = zone->GetZoneRaw(); - if (raw.chunks.empty()) { - ChatPackets::SendSystemMessage(sysAddr, u"Zone does not have valid terrain data."); - return; - } - - uint32_t spawnedCount = 0; - std::map sceneSpawnCounts; - - for (const auto& chunk : raw.chunks) { - if (!chunk.IsValidForSceneLookup()) continue; - - for (uint32_t i = 0; i < chunk.width; i += step) { - for (uint32_t j = 0; j < chunk.height; j += step) { - const uint8_t sceneID = chunk.GetSceneIDAtGrid(i, j); - if (sceneID == 0) continue; - - EntityInfo info; - info.lot = GetScenePointLot(sceneID); - info.pos = chunk.GridToWorldPos(i, j); - info.rot = QuatUtils::IDENTITY; - info.spawner = nullptr; - info.spawnerID = entity->GetObjectID(); - info.spawnerNodeID = 0; - info.settings.Insert(u"SpawnedFromSlashCommand", true); - - Entity* newEntity = Game::entityManager->CreateEntity(info, nullptr); - if (newEntity != nullptr) { - Game::entityManager->ConstructEntity(newEntity); - spawnedCount++; - sceneSpawnCounts[sceneID]++; - } - } - } - } - - // Send detailed feedback - std::ostringstream feedback; - feedback << "Spawned " << spawnedCount << " total points across " - << sceneSpawnCounts.size() << " scenes:\n"; - - for (const auto& [sceneID, count] : sceneSpawnCounts) { - const auto* sceneRef = zone->GetScene(LWOSCENEID(sceneID)); - const std::string sceneName = sceneRef ? sceneRef->name : "Unknown"; - feedback << " Scene " << static_cast(sceneID) << ", LOT: " << GetScenePointLot(sceneID) << " (" << sceneName << "): " << count << " points\n"; - } - ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(feedback.str())); } }; - diff --git a/dGame/dUtilities/SlashCommands/DEVGMCommands.h b/dGame/dUtilities/SlashCommands/DEVGMCommands.h index 228db51fb..05a3343a7 100644 --- a/dGame/dUtilities/SlashCommands/DEVGMCommands.h +++ b/dGame/dUtilities/SlashCommands/DEVGMCommands.h @@ -79,8 +79,6 @@ namespace DEVGMCommands { void Execute(Entity* entity, const SystemAddress& sysAddr, const std::string args); void GetScene(Entity* entity, const SystemAddress& sysAddr, const std::string args); void GetAdjacentScenes(Entity* entity, const SystemAddress& sysAddr, const std::string args); - void SpawnScenePoints(Entity* entity, const SystemAddress& sysAddr, const std::string args); - void SpawnAllScenePoints(Entity* entity, const SystemAddress& sysAddr, const std::string args); } #endif //!DEVGMCOMMANDS_H diff --git a/docs/Commands.md b/docs/Commands.md index 8f5a8690b..da487d106 100644 --- a/docs/Commands.md +++ b/docs/Commands.md @@ -145,8 +145,6 @@ These commands are primarily for development and testing. The usage of many of t |getnavmeshheight|`/getnavmeshheight`|Display the navmesh height at your current position|8| |getscene|`/getscene`|Display the scene ID and name at your current position (alias `/scene`)|8| |getadjacentscenes|`/getadjacentscenes`|List the scenes connected to your current scene by scene transitions (alias `/adjacentscenes`)|8| -|spawnscenepoints|`/spawnscenepoints (step)`|Spawns a brick every `step` terrain points (default 8) across your current scene|8| -|spawnallscenepoints|`/spawnallscenepoints (step)`|Spawns a brick every `step` terrain points (default 8) across every scene, one brick type per scene (alias `/spawnallscenes`)|8| |giveuscore|`/giveuscore `|Gives uscore|8| |gmadditem|`/gmadditem (count)`|Adds the given item to your inventory by id. Aliases: `/give`.|8| |inspect|`/inspect (-m | -a | -s | -p | -f (faction) | -t)`|Finds the closest entity with the given component or LNV variable (ignoring players and racing cars), printing its ID, distance from the player, and whether it is sleeping, as well as the IDs of all components the entity has. Use `localCharacter` or `zoneControl` to inspect your current character or the zone control object.|8| diff --git a/tests/dGameTests/dZoneManagerTests/ZoneSceneTests.cpp b/tests/dGameTests/dZoneManagerTests/ZoneSceneTests.cpp index c39f004ec..12d161552 100644 --- a/tests/dGameTests/dZoneManagerTests/ZoneSceneTests.cpp +++ b/tests/dGameTests/dZoneManagerTests/ZoneSceneTests.cpp @@ -5,8 +5,6 @@ #include #include "AssetManager.h" -#include "CDBrickIDTableTable.h" -#include "CDComponentsRegistryTable.h" #include "CDZoneTableTable.h" #include "DEVGMCommands.h" #include "Entity.h" @@ -230,41 +228,16 @@ TEST_F(ZoneSceneTest, UnreadableRawStillLoadsTheZone) { EXPECT_EQ(Game::zoneManager->GetSceneIDFromPosition(NiPoint3(0.5f, 0.0f, 0.5f)), LWOSCENEID_INVALID); } -TEST_F(ZoneSceneTest, ScenePointCommandsSpawnBricks) { +TEST_F(ZoneSceneTest, SceneCommandsReport) { WriteZone(); WriteFile("test.raw", MakeRaw()); LoadZone(); - auto& bricks = CDClientManager::GetEntriesMutable(); - bricks = { { 40, 3005 }, { 33, 3001 }, { 35, 3003 } }; - // the bricks have no components, so creating them needs no client database - for (const LOT lot : { 33, 35, 40 }) CDClientManager::GetEntriesMutable()[lot] = 0; - EntityInfo playerInfo = info; playerInfo.pos = NiPoint3(0.5f, 0.0f, 0.5f); // scene 1 auto player = std::make_unique(1, playerInfo); - // Grid point (i, j) is at (2i, 2j); its scene cell is (min(i, 1), min(j, 1)), so of the 9 points scene 1 has 5, - // scene 2 has 2 ((0, 1), (0, 2)) and scene 3 has 2 ((1, 0), (2, 0)) - DEVGMCommands::SpawnScenePoints(player.get(), UNASSIGNED_SYSTEM_ADDRESS, "1"); - // bricks sorted by LOT: 33, 35, 40; scene 1 -> 35, scene 2 -> 40, scene 3 -> 33 - const auto sceneOne = Game::entityManager->GetEntitiesByLOT(35); - EXPECT_EQ(sceneOne.size(), 5); - for (const auto* brick : sceneOne) EXPECT_EQ(Game::zoneManager->GetSceneIDFromPosition(brick->GetPosition()), LWOSCENEID(1, 0)); - EXPECT_TRUE(Game::entityManager->GetEntitiesByLOT(40).empty()); - - // the default step of 8 only samples point (0, 0) - DEVGMCommands::SpawnAllScenePoints(player.get(), UNASSIGNED_SYSTEM_ADDRESS, ""); - EXPECT_EQ(Game::entityManager->GetEntitiesByLOT(35).size(), 5 + 1); - EXPECT_TRUE(Game::entityManager->GetEntitiesByLOT(40).empty()); - - DEVGMCommands::SpawnAllScenePoints(player.get(), UNASSIGNED_SYSTEM_ADDRESS, "1"); - EXPECT_EQ(Game::entityManager->GetEntitiesByLOT(35).size(), 6 + 5); - EXPECT_EQ(Game::entityManager->GetEntitiesByLOT(40).size(), 2); - EXPECT_EQ(Game::entityManager->GetEntitiesByLOT(33).size(), 2); - - // the scene commands only report; they must not fail with or without scene data + // the scene commands only report; they must not fail DEVGMCommands::GetScene(player.get(), UNASSIGNED_SYSTEM_ADDRESS, ""); DEVGMCommands::GetAdjacentScenes(player.get(), UNASSIGNED_SYSTEM_ADDRESS, ""); - bricks.clear(); }