// ====================================================================== // // ConsoleCommandParserObject.cpp // copyright (c) 2001 Sony Online Entertainment // // ====================================================================== #include "serverGame/FirstServerGame.h" #include "serverGame/ConsoleCommandParserObject.h" #include "UnicodeUtils.h" #include "serverGame/AiCreatureController.h" #include "serverGame/BattlefieldMarkerObject.h" #include "serverGame/BuildingObject.h" #include "serverGame/Chat.h" #include "serverGame/Client.h" #include "serverGame/CommandQueue.h" #include "serverGame/CommoditiesMarket.h" #include "serverGame/ConfigServerGame.h" #include "serverGame/ConsentManager.h" #include "serverGame/ContainerInterface.h" #include "serverGame/CreatureObject.h" #include "serverGame/GameServer.h" #include "serverGame/InstallationObject.h" #include "serverGame/IntangibleObject.h" #include "serverGame/MoveSimManager.h" #include "serverGame/NameManager.h" #include "serverGame/NewbieTutorial.h" #include "serverGame/ObjectCommandParserGetAttributes.h" #include "serverGame/ObjectCommandParserSetAttributes.h" #include "serverGame/PlayerCreationManagerServer.h" #include "serverGame/PlayerCreatureController.h" #include "serverGame/PlayerObject.h" #include "serverGame/ProsePackageManagerServer.h" #include "serverGame/Region.h" #include "serverGame/RegionMaster.h" #include "serverGame/ServerController.h" #include "serverGame/ServerManufactureSchematicObjectTemplate.h" #include "serverGame/ServerMessageForwarding.h" #include "serverGame/ServerObject.h" #include "serverGame/ServerShipObjectTemplate.h" #include "serverGame/ServerWorld.h" #include "serverGame/ShipObject.h" #include "serverGame/TangibleObject.h" #include "serverGame/TriggerVolume.h" #include "serverGame/UniverseObject.h" #include "serverNetworkMessages/AccountFeatureIdRequest.h" #include "serverNetworkMessages/AdjustAccountFeatureIdRequest.h" #include "serverNetworkMessages/LocateStructureMessage.h" #include "serverNetworkMessages/ReloadTemplateMessage.h" #include "serverNetworkMessages/RenameCharacterMessage.h" #include "serverNetworkMessages/TransferCharacterData.h" #include "serverNetworkMessages/TransferCharacterDataArchive.h" #include "serverNetworkMessages/UnloadObjectMessage.h" #include "serverPathfinding/CityPathGraphManager.h" #include "serverPathfinding/PathAutoGenerator.h" #include "serverScript/GameScriptObject.h" #include "serverScript/ScriptParameters.h" #include "serverUtility/LocationData.h" #include "sharedCollision/CollisionProperty.h" #include "sharedCollision/CollisionWorld.h" #include "sharedCollision/Footprint.h" #include "sharedFile/FileManifest.h" #include "sharedFoundation/CalendarTime.h" #include "sharedFoundation/ConstCharCrcLowerString.h" #include "sharedFoundation/Crc.h" #include "sharedFoundation/FormattedString.h" #include "sharedFoundation/GameControllerMessage.h" #include "sharedFoundation/Production.h" #include "sharedGame/CommandTable.h" #include "sharedGame/PlatformFeatureBits.h" #include "sharedGame/PlayerData.h" #include "sharedGame/ProsePackage.h" #include "sharedGame/SharedStringIds.h" #include "sharedLog/Log.h" #include "sharedMath/Quaternion.h" #include "sharedNetworkMessages/AIDebuggingMessages.h" #include "sharedNetworkMessages/GenericValueTypeMessage.h" #include "sharedNetworkMessages/MessageQueueDataTransform.h" #include "sharedNetworkMessages/MessageQueueGenericValueType.h" #include "sharedObject/CellProperty.h" #include "sharedObject/ContainedByProperty.h" #include "sharedObject/NetworkIdManager.h" #include "sharedObject/ObjectTemplateList.h" #include "sharedObject/SlotIdManager.h" #include "sharedObject/SlottedContainer.h" #include "sharedObject/VolumeContainer.h" #include "sharedObject/VolumeContainmentProperty.h" #include "sharedSkillSystem/SkillObject.h" #include "sharedTerrain/TerrainObject.h" #include "sharedUtility/DataTable.h" #include "sharedUtility/DataTableManager.h" #include #if defined(_WIN32) && PRODUCTION == 0 #include "sharedDebug/VTune.h" #endif namespace ConsoleCommandParserObjectNamespace { //test handler, this should eventually be removed void testConsentHandler(const NetworkId& player, int id, bool response) { int i = 0; if (response == true) i = 1; DEBUG_REPORT_LOG(true, ("We received a test consent back with values NetworkId:%s Id:%d Response:%d\n", player.getValueString().c_str(), id, i)); } ServerObjectTemplate const *getObjectTemplateForCreation(std::string const &templateName) { // only allow non-ship ServerObjectTemplates ObjectTemplate const * const ot = ObjectTemplateList::fetch(templateName); if (ot) { ServerObjectTemplate const * const sot = ot->asServerObjectTemplate(); if (!sot) { WARNING(true, ("ConsoleCommandParserObject invalid object template [%s]", templateName.c_str())); ot->releaseReference(); return NULL; } if (sot->getId() == ServerShipObjectTemplate::ServerShipObjectTemplate_tag) { SharedObjectTemplate const * const sharedTemplate = safe_cast(ObjectTemplateList::fetch(sot->getSharedTemplate())); if (NULL == sharedTemplate || (sharedTemplate->getGameObjectType() != SharedObjectTemplate::GOT_ship_mining_asteroid_dynamic && sharedTemplate->getGameObjectType() != SharedObjectTemplate::GOT_ship_mining_asteroid_static)) { ot->releaseReference(); return NULL; } } return sot; } return NULL; } void checkBadBuildClusterObject(ServerObject *& o) { if ( ConfigServerGame::getBuildCluster() && o && !o->asTangibleObject() && !o->asStaticObject()) { o->permanentlyDestroy(DeleteReasons::SetupFailed); o = 0; } } typedef std::vector StringVector; typedef std::vector StoredStrings; typedef std::map PlayerStoredStringMap; PlayerStoredStringMap s_playerObjectTemplateMap; PlayerStoredStringMap s_playerCreatureNameMap; int const MAX_STORED_STRINGS = 50; std::string getStringShortcut(NetworkId const & userId, std::string const & tmpString, PlayerStoredStringMap const & playerStoredStringMap) { int stringIndex = 0; sscanf(tmpString.c_str(), "%d", &stringIndex); // decrement the string index so it starts at 0 --stringIndex; // if no shortcut number was entered, return the original string if (stringIndex < 0) return tmpString; PlayerStoredStringMap::const_iterator objectMapIter = playerStoredStringMap.find(userId); if (objectMapIter != playerStoredStringMap.end()) { const StoredStrings & storedStrings = objectMapIter->second; if (stringIndex >= 0 && stringIndex < (int)storedStrings.size()) { return storedStrings[stringIndex]; } } return tmpString; } std::string getObjectTemplateShortcut(NetworkId const & userId, std::string const & tmpString) { return getStringShortcut(userId, tmpString, s_playerObjectTemplateMap); } std::string getCreatureNameShortcut(NetworkId const & userId, std::string const & tmpString) { return getStringShortcut(userId, tmpString, s_playerCreatureNameMap); } char const * const s_creaureDataTable = "datatables/mob/creatures.iff"; typedef std::string (*searchNamesFormatterFunction) (std::string const & preFormattedString, int const index); std::string searchNamesCreatureFormatter(std::string const & creatureName, int const index) { bool const openIfNotFound = true; DataTable const * const dataTable = DataTableManager::getTable(s_creaureDataTable, openIfNotFound); std::string result; if (dataTable) { int const row = dataTable->searchColumnString(0, creatureName); if (row > -1) { int const baseLevel = dataTable->getIntValue("BaseLevel", row); int const difficultyClass = dataTable->getIntValue("difficultyClass", row); std::string const socialGroup = dataTable->getStringValue("socialGroup", row); std::string const pvpFaction = dataTable->getStringValue("pvpFaction", row); bool const invulnerable = dataTable->getIntValue("invulnerable", row); float const aggressive = dataTable->getFloatValue("aggressive", row); float const assist = dataTable->getFloatValue("assist", row); int const deathBlow = dataTable->getIntValue("death_blow", row); FormattedString<512> fs; result += fs.sprintf("\t%4d - L:%3d (%-7s) %s (%s,%s", index, baseLevel, difficultyClass == 0 ? "NORMAL" : difficultyClass == 1 ? "ELITE" : difficultyClass == 2 ? "BOSS" : "UNKNOWN", creatureName.c_str(), socialGroup.empty() ? "NONE" : socialGroup.c_str(), pvpFaction.empty() ? "NONE" : pvpFaction.c_str()); if (aggressive > 0) result += fs.sprintf(",AGGRO:%.0f", aggressive); if (assist > 0) result += fs.sprintf(",ASSIST:%.0f", assist); if (deathBlow > 0) result += ",DB"; if (invulnerable) result += ",INV"; result += ")\n"; } } return result.empty() ? FormattedString<512>().sprintf("\t%4d - %s\n", index, creatureName.c_str()) : result; } std::string searchNamesDefaultFormatter(std::string const & preFormattedString, int const index) { return FormattedString<512>().sprintf("\t%4d - %s\n", index, preFormattedString.c_str()); } //-- given a vector of string names std::string searchNames(StringVector const & namesToSearch, StringVector const & desiredSubStrings, char const * const exclusionString, StringVector & foundNames, searchNamesFormatterFunction formatterFunction = searchNamesDefaultFormatter) { std::string result; bool tooManyEntries = false; StringVector::const_iterator itName = namesToSearch.begin(); for (; itName != namesToSearch.end(); ++itName) { if (!itName->empty()) { std::string const name(*itName); // if it matches the exclusion string, skip if (exclusionString && name.find(exclusionString) != std::string::npos) continue; // check all desired substrings bool skipName = false; for (int i = 0; i < (int)desiredSubStrings.size(); ++i) { if (name.find(desiredSubStrings[i]) == std::string::npos) { skipName = true; break; } } if (skipName) continue; // check for too many entries if (foundNames.size() >= (int)MAX_STORED_STRINGS) { tooManyEntries = true; break; } // otherwise, we have one we want, add it to the vector foundNames.push_back(name); } } if (foundNames.size() == 0) { result += "Unable to find any matching objects.\n"; } else { std::sort(foundNames.begin(), foundNames.end()); for (int k = 0; k < (int)foundNames.size(); ++k) { result += formatterFunction ? formatterFunction(foundNames[k], k+1) : searchNamesDefaultFormatter(foundNames[k], k+1); } if (tooManyEntries) result += "\tToo many entries! Please refine search.\n"; } return result; } #ifdef USE_ALTERNATE_BUILD_REGION_CALCULATION bool isInNoBuildRegion( real x, real y ) { DEBUG_REPORT_LOG_PRINT( true, ( "isInNoBuildRegion: %f, %f\n", x, y ) ); RegionMaster::RegionVector v; RegionMaster::getRegionsAtPoint( ConfigServerGame::getSceneID(), x, y, v ); RegionMaster::RegionVector::const_iterator it; for ( it = v.begin(); it != v.end(); ++it ) { DEBUG_REPORT_LOG_PRINT( true, ( "checking region '%s' %d\n", Unicode::wideToNarrow( (*it)->getName() ).c_str(), (*it)->getBuildable() ) ); if ( (*it)->getBuildable() == 0 ) { return true; } } return false; } #endif std::set s_unmoveable; } using namespace ConsoleCommandParserObjectNamespace; // ====================================================================== static const CommandParser::CmdInfo cmds[] = { {"addLocationTarget", 6, " ", "Sets a location target for an object. onArrivedAtLocation will be triggered on the object, and messageHandler OnArrivedAtLocation() invoked on attached scripts."}, {"authority", 2, " ", "Transfer authority of object to gameserver ."}, {"create", 4, " ", "Create a new object."}, {"cellCreate", 4, " ", "Create a new object in a cell."}, {"count", 0, "", "Returns the number of objects allocated on this game server"}, {"createAt", 1, "", "Create a new object where you are standing."}, {"createManyAt", 2, " ", "Create new objects around where you are standing."}, {"createIn", 2, " ", "Create a new object in a container."}, {"createTranslateRotate", 8, " ", "Create a new object."}, {"cellCreateTranslateRotate", 8, " ", "Create a new object in a cell."}, {"createTriggerVolume", 3, " ", "Create a new trigger volume on the specified object."}, {"destroy", 1, "", "Destroy an existing object."}, {"destroyAllMobsExcept", 1, "", "Destroy all mobs except the given one."}, {"destroyAllWorldMobs", 0, "", "Destroy all mobs in the world cell."}, {"find", 1, "", "Find the coords of an existing object."}, {"findCreature", 1, " [string2] ...", "Search for creature names containing all string arguments. Index may be used instead of string name for commands that use a creature name (like spawn). Output displays:\n\tindex - L:level (difficulty class) name (social group, pvp faction, [aggro radius, assist radius, Death Blow, INVulernable]) where square bracketed [] fields display only if applicable."}, {"findTemplate", 1, "", "Find ."}, {"findRelative_w", 1, "", "Find the your coords relative to an existing object."}, {"fixHouseItemLimit", 1, "", "Fixup item limit."}, {"getHeight", 0, "", "Get the height where the user is standing."}, {"getInventoryId", 1, "", "Get the inventory object for the specified creature."}, {"getDatapadId", 1, "", "Get the datapad object for the specified player."}, {"getServerTemplate", 1, "", "Get the server template name of an object."}, {"getExposedProxyList", 1, "", "Get the exposed list of servers the specified object is proxied on."}, {"getPrivateProxyList", 1, "", "Get the private list of servers the specified object is proxied on."}, {"getObservers", 1, "", "Get the list of clients currently observing the specified object on this game server."}, {"getObserving", 1, "", "Get the list of objects this client is observing. (brief version)"}, {"getObservingDetailed", 1, "", "Get the list of objects this client is observing. (detailed version)"}, {"getObservingPvpSync", 1, "", "Get the list of pvp sync objects this client is observing. (brief version)"}, {"getObservingPvpSyncDetailed", 1, "", "Get the list of pvp sync objects this client is observing. (detailed version)"}, {"getLoadWith", 1, "", "Get the loadWith container of an object.h"}, {"getVolume", 1, "", "Get the volume of an object"}, {"gotoObject", 1, "", "Goto the coords of an existing object. currently disabled."}, {"isIncapacitated", 1, "", "Gets the incapacitated state of a creature"}, {"isProxy", 1, "", "Query as to whether this is a proxy on the avatar's server."}, {"listContainer", 1, "", "Lists the contents of a volume container object."}, {"loadContents", 1, " [oid]", "Load an object in the specified demand-load container. If oid is not specified, the entire contents are loaded."}, {"move", 4, " ", "Move an existing object."}, {"moveToMe", 1, "", "Move an existing object to my coordinates."}, {"persist", 1, "", "Persist an object."}, {"reloadServerTemplate", 1, "", "Reloads the given server object template."}, {"removeLocationTarget", 2, " ", "Removes a location target from an object."}, {"removeTriggerVolume", 2, " ", "Remove the named trigger volume from the specified object."}, {"renamePlayer", 2, " ", "Rename a player. Naming rules and uniqueness are not enforced."}, {"rotate", 4, " ", "Rotate an existing object."}, {"scaleMovement", 2, " ", "Set the movement scale on a creature."}, {"scaleSize", 2, " ", "Set the size scale of a creature."}, {"snap", 1, "", "Snap an object to the terrain."}, {"spawn", 1, " [number] [distance] [spacing]", "Create [number](1) creature objects at [distance](1.25) meters with [spacing](creature's collision diameter) meters from the player's position and heading."}, {"stopWatching", 1, "", "Stops watching an object."}, {"triggerVolumes", 1, "", "List trigger volumes on an object"}, {"setName" , 1, " ", "Set name."}, {"watch", 1, "", "Watches an object. Prevents it from unloading on the server (it will still be removed from the client) when there are no players in range."}, {"watchAIPath", 2, " ", "Enable or disable sending of the selected object's path"}, {"watchPathMap", 1, "", "Enable or disable sending the path map"}, {"unstick", 0, "", "Ask the server to get this object un-stuck if it's become stuck due to collision problems"}, {"attribs", 1, "", "Prints the attributes of a creature."}, {"enqueueCommand", 4, " ", "enqueue a command in the actor's command queue"}, {"hide", 2, " ", "Set the target as invisible (1) or visible(0)"}, {"setCoverVisibility", 2, " ", "Set the target cover visibility as visible (1) or invisible(0)"}, {"getAttributes", 1, "", "Get the list of attributes that would be sent in a AttributesMessage for the specified object"}, {"createPathNodes", 1, "", "Create city path nodes for the given object"}, {"destroyPathNodes", 1, "", "Destroy city path nodes for the given object"}, {"reloadPathNodes", 0, "", "Reload all city path nodes from the database"}, {"relinkPathGraph", 0, "", "Relink all path nodes in the current city"}, {"setPathLinkDistance", 1, "", "Set the maximum distance that path nodes will link"}, {"markCityEntrance", 1, "", "Mark the given object as a city entrance node"}, {"unmarkCityEntrance", 1, "", "Remove the city entrance mark from the given object"}, {"setOwner", 1, " [owner]", "Sets the owner of an object"}, {"getOwner", 1, "", "gets the owner of an object"}, {"askConsent", 0, "", "TEST: ask a test consent question"}, {"debugFar", 2, " ", "Create or destroy a far volume on an object. If a radius is specified, the object will use that radius."}, {"addJediSlot", 1, "", "Test a character earning a Jedi slot for his player (oid is the objectId of the player's creature object)"}, {"getJediSlotInfo", 1, "", "Get various information about the Jedi slot for the character"}, {"makeSpectral", 1, "", "Test making a character spectral in the account database."}, {"getHibernating", 1, "", "Get the hibernate flag for a creature"}, {"getBehavior", 1, "", "Get the behavior type for a creature"}, {"getStandingOn", 1, "", "Get the network ID of the object a creature is standing on"}, {"getPower", 1, "", "Get the amount of power in an installation"}, {"setPower", 2, " power", "Set the amount of power in an installation"}, {"getPowerRate", 1, "", "Get the power consuption (units/hr) of an installation"}, {"setPowerRate", 2, " rate", "Set the power consuption (units/hr) of an installation"}, {"getBattlefieldMarkerRegionName", 1, "", "Get the region name of a battlefield marker"}, {"setBattlefieldMarkerRegionName", 2, " ", "Set the region name of a battlefield marker"}, {"unload", 1, "", "Unload an object on all servers"}, {"moveToPlayerAndUnload", 2, " ", "Move an object to the specified offline player and unload the object"}, {"resetStats", 1, "", "Resets the stats of the given player to their starting values"}, {"restoreHouse", 1, "", "Restore a house in the database. (Do not use this to restore any other type of object.)"}, {"restoreCharacter", 1, "", "Restore a character in the database. (Do not use this to restore any other type of object.)"}, {"enableCharacter", 2, " ", "enable a character to play"}, {"disableCharacter", 2, " ", "disable a character to play"}, {"loginCharacter", 1, "", "logs in a character"}, {"undeleteItem", 1, "", "Undelete an item including house or character."}, {"loadStructure", 1, "", "Load a structure into game. This structure must not exist in game."}, {"deleteAuctionLocation", 1, "", "Delete an auction location from commodities server and database. The LocationId is either vendorId for droid vendors, or vendorInventoryId for NPC vendors"}, {"moveToPlayer", 2, " ", "Move an object to a player"}, {"moveSimStart", 4, " ", ""}, {"moveSimClear", 0, "", ""}, {"deletePersistedContents", 1, "", "Delete all the persisted contents in a house. (useful for objects in walls etc)"}, {"moveItemInHouseToMe", 2, " ", "Moves the first item in a house to me. An index of 0 indicates first item"}, {"reinitializeVendor", 1, "", "Reinitialize a vendor moving all items to the stockroom"}, {"testVendorStatus", 2, " ", "Status test"}, {"setAdminTitle", 1, "<0=none, 1=csr, 2=dev, 3=qa>", "Set your development title 0=none, 1=csr, 2=dev, 3=qa"}, {"playUiEffect", 0, " ", "Play a UI effect on the target client."}, {"rollupStructure", 2, " ", "Rollup a house and transfer the contents to the specified player's bank box."}, {"regionList", 0, "", "List regions at point."}, {"canMove", 0, "", "Can move to target"}, {"pathAutoGenerate", 2, " ", "gen"}, {"pathAutoCleanup", 0, "", "clean"}, {"getStaticInfo", 1, "", "Get the Static Item Information of an object"}, {"getBroadcastInfo", 1, "", "Get the broadcasting information of an object"}, {"getAge", 1, "", "Get the age (in days) for the specified character"}, {"adjustAge", 2, " ", "Adjust the age (in days) for the specified character"}, {"getBadge", 1, "", "Get the earned and unearned badges for the specified character"}, {"getPassiveReveal", 1, "