mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-08-04 01:34:07 +00:00
feat: debug features and implement ObjectDebugger (#1846)
Move the -s and base features of inspect to the object debugger (this file is present in an unmodified, live client)
This commit is contained in:
@@ -97,6 +97,8 @@
|
|||||||
#include "CDSkillBehaviorTable.h"
|
#include "CDSkillBehaviorTable.h"
|
||||||
#include "CDZoneTableTable.h"
|
#include "CDZoneTableTable.h"
|
||||||
|
|
||||||
|
#include "StringifiedEnum.h"
|
||||||
|
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
|
|
||||||
Observable<Entity*, const PositionUpdate&> Entity::OnPlayerPositionUpdate;
|
Observable<Entity*, const PositionUpdate&> Entity::OnPlayerPositionUpdate;
|
||||||
@@ -187,6 +189,7 @@ Entity::~Entity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Entity::Initialize() {
|
void Entity::Initialize() {
|
||||||
|
RegisterMsg(MessageType::Game::REQUEST_SERVER_OBJECT_INFO, this, &Entity::MsgRequestServerObjectInfo);
|
||||||
/**
|
/**
|
||||||
* Setup trigger
|
* Setup trigger
|
||||||
*/
|
*/
|
||||||
@@ -2209,3 +2212,38 @@ bool Entity::HandleMsg(GameMessages::GameMsg& msg) const {
|
|||||||
void Entity::RegisterMsg(const MessageType::Game msgId, std::function<bool(GameMessages::GameMsg&)> handler) {
|
void Entity::RegisterMsg(const MessageType::Game msgId, std::function<bool(GameMessages::GameMsg&)> handler) {
|
||||||
m_MsgHandlers.emplace(msgId, handler);
|
m_MsgHandlers.emplace(msgId, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Entity::MsgRequestServerObjectInfo(GameMessages::GameMsg& msg) {
|
||||||
|
auto& requestInfo = static_cast<GameMessages::RequestServerObjectInfo&>(msg);
|
||||||
|
AMFArrayValue response;
|
||||||
|
response.Insert("visible", true);
|
||||||
|
response.Insert("objectID", std::to_string(m_ObjectID));
|
||||||
|
response.Insert("serverInfo", true);
|
||||||
|
GameMessages::GetObjectReportInfo info{};
|
||||||
|
info.info = response.InsertArray("data");
|
||||||
|
auto& objectInfo = info.info->PushDebug("Object Details");
|
||||||
|
auto* table = CDClientManager::GetTable<CDObjectsTable>();
|
||||||
|
|
||||||
|
const auto& objTableInfo = table->GetByID(GetLOT());
|
||||||
|
|
||||||
|
objectInfo.PushDebug<AMFStringValue>("Name") = objTableInfo.name;
|
||||||
|
objectInfo.PushDebug<AMFIntValue>("Template ID(LOT)") = GetLOT();
|
||||||
|
objectInfo.PushDebug<AMFStringValue>("Object ID") = std::to_string(GetObjectID());
|
||||||
|
objectInfo.PushDebug<AMFStringValue>("Spawner's Object ID") = std::to_string(GetSpawnerID());
|
||||||
|
|
||||||
|
auto& componentDetails = objectInfo.PushDebug("Component Information");
|
||||||
|
for (const auto [id, component] : m_Components) {
|
||||||
|
componentDetails.PushDebug<AMFStringValue>(StringifiedEnum::ToString(id)) = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& configData = objectInfo.PushDebug("Config Data");
|
||||||
|
for (const auto config : m_Settings) {
|
||||||
|
configData.PushDebug<AMFStringValue>(GeneralUtils::UTF16ToWTF8(config->GetKey())) = config->GetValueAsString();
|
||||||
|
|
||||||
|
}
|
||||||
|
HandleMsg(info);
|
||||||
|
|
||||||
|
auto* targetForReport = Game::entityManager->GetEntity(requestInfo.targetForReport);
|
||||||
|
if (targetForReport) GameMessages::SendUIMessageServerToSingleClient("ToggleObjectDebugger", response, targetForReport->GetSystemAddress());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@@ -175,6 +175,8 @@ public:
|
|||||||
|
|
||||||
void AddComponent(eReplicaComponentType componentId, Component* component);
|
void AddComponent(eReplicaComponentType componentId, Component* component);
|
||||||
|
|
||||||
|
bool MsgRequestServerObjectInfo(GameMessages::GameMsg& msg);
|
||||||
|
|
||||||
// This is expceted to never return nullptr, an assert checks this.
|
// This is expceted to never return nullptr, an assert checks this.
|
||||||
CppScripts::Script* const GetScript() const;
|
CppScripts::Script* const GetScript() const;
|
||||||
|
|
||||||
@@ -336,6 +338,10 @@ public:
|
|||||||
|
|
||||||
bool HandleMsg(GameMessages::GameMsg& msg) const;
|
bool HandleMsg(GameMessages::GameMsg& msg) const;
|
||||||
|
|
||||||
|
void RegisterMsg(const MessageType::Game msgId, auto* self, const auto handler) {
|
||||||
|
RegisterMsg(msgId, std::bind(handler, self, std::placeholders::_1));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The observable for player entity position updates.
|
* @brief The observable for player entity position updates.
|
||||||
*/
|
*/
|
||||||
|
@@ -49,19 +49,13 @@ CharacterComponent::CharacterComponent(Entity* parent, Character* character, con
|
|||||||
m_LastUpdateTimestamp = std::time(nullptr);
|
m_LastUpdateTimestamp = std::time(nullptr);
|
||||||
m_SystemAddress = systemAddress;
|
m_SystemAddress = systemAddress;
|
||||||
|
|
||||||
RegisterMsg(MessageType::Game::REQUEST_SERVER_OBJECT_INFO, this, &CharacterComponent::OnRequestServerObjectInfo);
|
RegisterMsg(MessageType::Game::GET_OBJECT_REPORT_INFO, this, &CharacterComponent::OnGetObjectReportInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CharacterComponent::OnRequestServerObjectInfo(GameMessages::GameMsg& msg) {
|
bool CharacterComponent::OnGetObjectReportInfo(GameMessages::GameMsg& msg) {
|
||||||
auto& request = static_cast<GameMessages::RequestServerObjectInfo&>(msg);
|
auto& reportInfo = static_cast<GameMessages::GetObjectReportInfo&>(msg);
|
||||||
AMFArrayValue response;
|
|
||||||
|
|
||||||
response.Insert("visible", true);
|
auto& cmptType = reportInfo.info->PushDebug("Character");
|
||||||
response.Insert("objectID", std::to_string(request.targetForReport));
|
|
||||||
response.Insert("serverInfo", true);
|
|
||||||
|
|
||||||
auto& data = *response.InsertArray("data");
|
|
||||||
auto& cmptType = data.PushDebug("Character");
|
|
||||||
|
|
||||||
cmptType.PushDebug<AMFIntValue>("Component ID") = GeneralUtils::ToUnderlying(ComponentType);
|
cmptType.PushDebug<AMFIntValue>("Component ID") = GeneralUtils::ToUnderlying(ComponentType);
|
||||||
cmptType.PushDebug<AMFIntValue>("Character's account ID") = m_Character->GetParentUser()->GetAccountID();
|
cmptType.PushDebug<AMFIntValue>("Character's account ID") = m_Character->GetParentUser()->GetAccountID();
|
||||||
@@ -72,6 +66,13 @@ bool CharacterComponent::OnRequestServerObjectInfo(GameMessages::GameMsg& msg) {
|
|||||||
cmptType.PushDebug<AMFStringValue>("Total currency") = std::to_string(m_Character->GetCoins());
|
cmptType.PushDebug<AMFStringValue>("Total currency") = std::to_string(m_Character->GetCoins());
|
||||||
cmptType.PushDebug<AMFStringValue>("Currency able to be picked up") = std::to_string(m_DroppedCoins);
|
cmptType.PushDebug<AMFStringValue>("Currency able to be picked up") = std::to_string(m_DroppedCoins);
|
||||||
cmptType.PushDebug<AMFStringValue>("Tooltip flags value") = "0";
|
cmptType.PushDebug<AMFStringValue>("Tooltip flags value") = "0";
|
||||||
|
auto& vl = cmptType.PushDebug("Visited Levels");
|
||||||
|
for (const auto zoneID : m_VisitedLevels) {
|
||||||
|
std::stringstream sstream;
|
||||||
|
sstream << "MapID: " << zoneID.GetMapID() << " CloneID: " << zoneID.GetCloneID();
|
||||||
|
vl.PushDebug<AMFStringValue>(sstream.str()) = "";
|
||||||
|
}
|
||||||
|
|
||||||
// visited locations
|
// visited locations
|
||||||
cmptType.PushDebug<AMFBoolValue>("is a GM") = m_GMLevel > eGameMasterLevel::CIVILIAN;
|
cmptType.PushDebug<AMFBoolValue>("is a GM") = m_GMLevel > eGameMasterLevel::CIVILIAN;
|
||||||
cmptType.PushDebug<AMFBoolValue>("Has PVP flag turned on") = m_PvpEnabled;
|
cmptType.PushDebug<AMFBoolValue>("Has PVP flag turned on") = m_PvpEnabled;
|
||||||
@@ -83,9 +84,6 @@ bool CharacterComponent::OnRequestServerObjectInfo(GameMessages::GameMsg& msg) {
|
|||||||
cmptType.PushDebug<AMFIntValue>("Current Activity Type") = GeneralUtils::ToUnderlying(m_CurrentActivity);
|
cmptType.PushDebug<AMFIntValue>("Current Activity Type") = GeneralUtils::ToUnderlying(m_CurrentActivity);
|
||||||
cmptType.PushDebug<AMFDoubleValue>("Property Clone ID") = m_Character->GetPropertyCloneID();
|
cmptType.PushDebug<AMFDoubleValue>("Property Clone ID") = m_Character->GetPropertyCloneID();
|
||||||
|
|
||||||
GameMessages::SendUIMessageServerToSingleClient("ToggleObjectDebugger", response, m_Parent->GetSystemAddress());
|
|
||||||
|
|
||||||
LOG("Handled!");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -331,7 +331,7 @@ public:
|
|||||||
void LoadVisitedLevelsXml(const tinyxml2::XMLElement& doc);
|
void LoadVisitedLevelsXml(const tinyxml2::XMLElement& doc);
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool OnRequestServerObjectInfo(GameMessages::GameMsg& msg);
|
bool OnGetObjectReportInfo(GameMessages::GameMsg& msg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The map of active venture vision effects
|
* The map of active venture vision effects
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
#include "eGameMasterLevel.h"
|
#include "eGameMasterLevel.h"
|
||||||
|
|
||||||
class AMFBaseValue;
|
class AMFBaseValue;
|
||||||
|
class AMFArrayValue;
|
||||||
class Entity;
|
class Entity;
|
||||||
class Item;
|
class Item;
|
||||||
class NiQuaternion;
|
class NiQuaternion;
|
||||||
@@ -788,6 +789,13 @@ namespace GameMessages {
|
|||||||
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
void Handle(Entity& entity, const SystemAddress& sysAddr) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct GetObjectReportInfo : public GameMsg {
|
||||||
|
AMFArrayValue* info{};
|
||||||
|
bool bVerbose{};
|
||||||
|
|
||||||
|
GetObjectReportInfo() : GameMsg(MessageType::Game::GET_OBJECT_REPORT_INFO, eGameMasterLevel::DEVELOPER) {}
|
||||||
|
};
|
||||||
|
|
||||||
struct RequestUse : public GameMsg {
|
struct RequestUse : public GameMsg {
|
||||||
RequestUse() : GameMsg(MessageType::Game::REQUEST_USE) {}
|
RequestUse() : GameMsg(MessageType::Game::REQUEST_USE) {}
|
||||||
|
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
#include "DEVGMCommands.h"
|
#include "DEVGMCommands.h"
|
||||||
|
|
||||||
|
#include <ranges>
|
||||||
|
|
||||||
// Classes
|
// Classes
|
||||||
#include "AssetManager.h"
|
#include "AssetManager.h"
|
||||||
#include "Character.h"
|
#include "Character.h"
|
||||||
@@ -48,6 +50,7 @@
|
|||||||
#include "MessageType/Master.h"
|
#include "MessageType/Master.h"
|
||||||
#include "eInventoryType.h"
|
#include "eInventoryType.h"
|
||||||
#include "ePlayerFlag.h"
|
#include "ePlayerFlag.h"
|
||||||
|
#include "StringifiedEnum.h"
|
||||||
|
|
||||||
|
|
||||||
namespace DEVGMCommands {
|
namespace DEVGMCommands {
|
||||||
@@ -1514,7 +1517,12 @@ namespace DEVGMCommands {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!closest) return;
|
if (!closest) return;
|
||||||
LOG("%llu", closest->GetObjectID());
|
|
||||||
|
GameMessages::RequestServerObjectInfo objectInfo;
|
||||||
|
objectInfo.bVerbose = true;
|
||||||
|
objectInfo.target = closest->GetObjectID();
|
||||||
|
objectInfo.targetForReport = entity->GetObjectID();
|
||||||
|
closest->HandleMsg(objectInfo);
|
||||||
|
|
||||||
Game::entityManager->SerializeEntity(closest);
|
Game::entityManager->SerializeEntity(closest);
|
||||||
|
|
||||||
@@ -1528,16 +1536,6 @@ namespace DEVGMCommands {
|
|||||||
|
|
||||||
ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(header.str()));
|
ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(header.str()));
|
||||||
|
|
||||||
for (const auto& pair : closest->GetComponents()) {
|
|
||||||
auto id = pair.first;
|
|
||||||
|
|
||||||
std::stringstream stream;
|
|
||||||
|
|
||||||
stream << "Component [" << std::to_string(static_cast<uint32_t>(id)) << "]";
|
|
||||||
|
|
||||||
ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::ASCIIToUTF16(stream.str()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (splitArgs.size() >= 2) {
|
if (splitArgs.size() >= 2) {
|
||||||
if (splitArgs[1] == "-m" && splitArgs.size() >= 3) {
|
if (splitArgs[1] == "-m" && splitArgs.size() >= 3) {
|
||||||
auto* const movingPlatformComponent = closest->GetComponent<MovingPlatformComponent>();
|
auto* const movingPlatformComponent = closest->GetComponent<MovingPlatformComponent>();
|
||||||
@@ -1557,13 +1555,6 @@ namespace DEVGMCommands {
|
|||||||
Game::entityManager->SerializeEntity(closest);
|
Game::entityManager->SerializeEntity(closest);
|
||||||
} else if (splitArgs[1] == "-a" && splitArgs.size() >= 3) {
|
} else if (splitArgs[1] == "-a" && splitArgs.size() >= 3) {
|
||||||
RenderComponent::PlayAnimation(closest, splitArgs.at(2));
|
RenderComponent::PlayAnimation(closest, splitArgs.at(2));
|
||||||
} else if (splitArgs[1] == "-s") {
|
|
||||||
for (auto* entry : closest->GetSettings()) {
|
|
||||||
ChatPackets::SendSystemMessage(sysAddr, GeneralUtils::UTF8ToUTF16(entry->GetString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatPackets::SendSystemMessage(sysAddr, u"------");
|
|
||||||
ChatPackets::SendSystemMessage(sysAddr, u"Spawner ID: " + GeneralUtils::to_u16string(closest->GetSpawnerID()));
|
|
||||||
} else if (splitArgs[1] == "-p") {
|
} else if (splitArgs[1] == "-p") {
|
||||||
const auto postion = closest->GetPosition();
|
const auto postion = closest->GetPosition();
|
||||||
|
|
||||||
|
@@ -81,28 +81,25 @@ void WorldPackets::SendServerState(const SystemAddress& sysAddr) {
|
|||||||
SEND_PACKET;
|
SEND_PACKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldPackets::SendCreateCharacter(const SystemAddress& sysAddr, int64_t reputation, LWOOBJID player, const std::string& xmlData, const std::u16string& username, eGameMasterLevel gm) {
|
void WorldPackets::SendCreateCharacter(const SystemAddress& sysAddr, int64_t reputation, LWOOBJID player, const std::string& xmlData, const std::u16string& username, eGameMasterLevel gm, const LWOCLONEID cloneID) {
|
||||||
|
using namespace std;
|
||||||
RakNet::BitStream bitStream;
|
RakNet::BitStream bitStream;
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::CREATE_CHARACTER);
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::CREATE_CHARACTER);
|
||||||
|
|
||||||
RakNet::BitStream data;
|
RakNet::BitStream data;
|
||||||
data.Write<uint32_t>(7); //LDF key count
|
|
||||||
|
|
||||||
std::unique_ptr<LDFData<LWOOBJID>> objid(new LDFData<LWOOBJID>(u"objid", player));
|
std::vector<std::unique_ptr<LDFBaseData>> ldfData;
|
||||||
std::unique_ptr<LDFData<LOT>> lot(new LDFData<LOT>(u"template", 1));
|
ldfData.push_back(move(make_unique<LDFData<LWOOBJID>>(u"objid", player)));
|
||||||
std::unique_ptr<LDFData<std::string>> xmlConfigData(new LDFData<std::string>(u"xmlData", xmlData));
|
ldfData.push_back(move(make_unique<LDFData<LOT>>(u"template", 1)));
|
||||||
std::unique_ptr<LDFData<std::u16string>> name(new LDFData<std::u16string>(u"name", username));
|
ldfData.push_back(move(make_unique<LDFData<string>>(u"xmlData", xmlData)));
|
||||||
std::unique_ptr<LDFData<int32_t>> gmlevel(new LDFData<int32_t>(u"gmlevel", static_cast<int32_t>(gm)));
|
ldfData.push_back(move(make_unique<LDFData<u16string>>(u"name", username)));
|
||||||
std::unique_ptr<LDFData<int32_t>> chatmode(new LDFData<int32_t>(u"chatmode", static_cast<int32_t>(gm)));
|
ldfData.push_back(move(make_unique<LDFData<int32_t>>(u"gmlevel", static_cast<int32_t>(gm))));
|
||||||
std::unique_ptr<LDFData<int64_t>> reputationLdf(new LDFData<int64_t>(u"reputation", reputation));
|
ldfData.push_back(move(make_unique<LDFData<int32_t>>(u"chatmode", static_cast<int32_t>(gm))));
|
||||||
|
ldfData.push_back(move(make_unique<LDFData<int64_t>>(u"reputation", reputation)));
|
||||||
|
ldfData.push_back(move(make_unique<LDFData<int32_t>>(u"propertycloneid", cloneID)));
|
||||||
|
|
||||||
objid->WriteToPacket(data);
|
data.Write<uint32_t>(ldfData.size());
|
||||||
lot->WriteToPacket(data);
|
for (const auto& toSerialize : ldfData) toSerialize->WriteToPacket(data);
|
||||||
name->WriteToPacket(data);
|
|
||||||
gmlevel->WriteToPacket(data);
|
|
||||||
chatmode->WriteToPacket(data);
|
|
||||||
xmlConfigData->WriteToPacket(data);
|
|
||||||
reputationLdf->WriteToPacket(data);
|
|
||||||
|
|
||||||
//Compress the data before sending:
|
//Compress the data before sending:
|
||||||
const uint32_t reservedSize = ZCompression::GetMaxCompressedLength(data.GetNumberOfBytesUsed());
|
const uint32_t reservedSize = ZCompression::GetMaxCompressedLength(data.GetNumberOfBytesUsed());
|
||||||
|
@@ -31,7 +31,7 @@ namespace WorldPackets {
|
|||||||
void SendCharacterDeleteResponse(const SystemAddress& sysAddr, bool response);
|
void SendCharacterDeleteResponse(const SystemAddress& sysAddr, bool response);
|
||||||
void SendTransferToWorld(const SystemAddress& sysAddr, const std::string& serverIP, uint32_t serverPort, bool mythranShift);
|
void SendTransferToWorld(const SystemAddress& sysAddr, const std::string& serverIP, uint32_t serverPort, bool mythranShift);
|
||||||
void SendServerState(const SystemAddress& sysAddr);
|
void SendServerState(const SystemAddress& sysAddr);
|
||||||
void SendCreateCharacter(const SystemAddress& sysAddr, int64_t reputation, LWOOBJID player, const std::string& xmlData, const std::u16string& username, eGameMasterLevel gm);
|
void SendCreateCharacter(const SystemAddress& sysAddr, int64_t reputation, LWOOBJID player, const std::string& xmlData, const std::u16string& username, eGameMasterLevel gm, const LWOCLONEID cloneID);
|
||||||
void SendChatModerationResponse(const SystemAddress& sysAddr, bool requestAccepted, uint32_t requestID, const std::string& receiver, std::set<std::pair<uint8_t, uint8_t>> unacceptedItems);
|
void SendChatModerationResponse(const SystemAddress& sysAddr, bool requestAccepted, uint32_t requestID, const std::string& receiver, std::set<std::pair<uint8_t, uint8_t>> unacceptedItems);
|
||||||
void SendGMLevelChange(const SystemAddress& sysAddr, bool success, eGameMasterLevel highestLevel, eGameMasterLevel prevLevel, eGameMasterLevel newLevel);
|
void SendGMLevelChange(const SystemAddress& sysAddr, bool success, eGameMasterLevel highestLevel, eGameMasterLevel prevLevel, eGameMasterLevel newLevel);
|
||||||
void SendHTTPMonitorInfo(const SystemAddress& sysAddr, const HTTPMonitorInfo& info);
|
void SendHTTPMonitorInfo(const SystemAddress& sysAddr, const HTTPMonitorInfo& info);
|
||||||
|
@@ -1040,7 +1040,7 @@ void HandlePacket(Packet* packet) {
|
|||||||
auto* characterComponent = player->GetComponent<CharacterComponent>();
|
auto* characterComponent = player->GetComponent<CharacterComponent>();
|
||||||
if (!characterComponent) return;
|
if (!characterComponent) return;
|
||||||
|
|
||||||
WorldPackets::SendCreateCharacter(packet->systemAddress, player->GetComponent<CharacterComponent>()->GetReputation(), player->GetObjectID(), c->GetXMLData(), username, c->GetGMLevel());
|
WorldPackets::SendCreateCharacter(packet->systemAddress, player->GetComponent<CharacterComponent>()->GetReputation(), player->GetObjectID(), c->GetXMLData(), username, c->GetGMLevel(), c->GetPropertyCloneID());
|
||||||
WorldPackets::SendServerState(packet->systemAddress);
|
WorldPackets::SendServerState(packet->systemAddress);
|
||||||
|
|
||||||
const auto respawnPoint = player->GetCharacter()->GetRespawnPoint(Game::zoneManager->GetZone()->GetWorldID());
|
const auto respawnPoint = player->GetCharacter()->GetRespawnPoint(Game::zoneManager->GetZone()->GetWorldID());
|
||||||
|
@@ -121,15 +121,15 @@ These commands are primarily for development and testing. The usage of many of t
|
|||||||
|
|
||||||
## Detailed `/inspect` Usage
|
## Detailed `/inspect` Usage
|
||||||
|
|
||||||
`/inspect <component> (-m <waypoint> | -a <animation> | -s | -p | -f (faction) | -t)`
|
`/inspect <component> (-m <waypoint> | -a <animation> | -p | -f (faction) | -t)`
|
||||||
|
|
||||||
Finds the closest entity with the given component or LDF variable (ignoring players and racing cars), printing its ID, distance from the player, and whether it is sleeping, as well as the the IDs of all components the entity has.
|
Finds the closest entity with the given component or LDF variable (ignoring players and racing cars), printing its ID, distance from the player, and whether it is sleeping, as well as the the IDs of all components the entity has.
|
||||||
|
This info is then shown in a window on the client which the user can navigate
|
||||||
|
|
||||||
### `/inspect` Options
|
### `/inspect` Options
|
||||||
|
|
||||||
* `-m`: If the entity has a moving platform component, sends it to the given waypoint, or stops the platform if `waypoint` is `-1`.
|
* `-m`: If the entity has a moving platform component, sends it to the given waypoint, or stops the platform if `waypoint` is `-1`.
|
||||||
* `-a`: Plays the given animation on the entity.
|
* `-a`: Plays the given animation on the entity.
|
||||||
* `-s`: Prints the entity's settings and spawner ID.
|
|
||||||
* `-p`: Prints the entity's position
|
* `-p`: Prints the entity's position
|
||||||
* `-f`: If the entity has a destroyable component, prints whether the entity is smashable and its friendly and enemy faction IDs; if `faction` is specified, adds that faction to the entity.
|
* `-f`: If the entity has a destroyable component, prints whether the entity is smashable and its friendly and enemy faction IDs; if `faction` is specified, adds that faction to the entity.
|
||||||
* `-cf`: check if the entity is enemy or friend
|
* `-cf`: check if the entity is enemy or friend
|
||||||
|
Reference in New Issue
Block a user