// ====================================================================== // // ConsoleCommandParserObjvar.cpp // copyright (c) 2001 Sony Online Entertainment // // ====================================================================== #include "serverGame/FirstServerGame.h" #include "serverGame/ConsoleCommandParserObjvar.h" #include "UnicodeUtils.h" #include "serverGame/CreatureObject.h" #include "serverGame/ServerObject.h" #include "serverGame/ServerWorld.h" #include "sharedFoundation/DynamicVariable.h" #include "sharedFoundation/DynamicVariableList.h" #include "sharedFoundation/DynamicVariableListNestedList.h" #include "sharedFoundation/DynamicVariableLocationData.h" #include "sharedFoundation/FormattedString.h" #include "sharedFoundation/NetworkId.h" #include "sharedGame/GameObjectTypes.h" #include // ====================================================================== //TODO: A lot of this file could be replaced by calls to ObjectVariable::debugPrint(), but need to make sure the formatting is consistent whith // what the god client expects // value types for set objvar enum { INT_ARGUMENT, REAL_ARGUMENT, STRING_ARGUMENT }; static const CommandParser::CmdInfo cmds[] = { {"set", 3, " ", "Sets an objvar for an object."}, {"setlist",2, " ", "Creates a new objvar list."}, {"get", 2, " ", "Prints the value of an objvar."}, {"list", 0, "", "Lists all the objvars on an object."}, {"listWithPacking", 1, "", "Lists all the objvars on an object, showing which are packed into the OBJECTS table in the database."}, {"remove", 2, " ", "Removes an objvar from an object."}, {"", 0, "", ""} // this must be last }; //----------------------------------------------------------------- static std::string getDebugString(Transform const &tr) { Vector i(tr.getLocalFrameI_p()); Vector j(tr.getLocalFrameJ_p()); Vector k(tr.getLocalFrameK_p()); Vector p(tr.getPosition_p()); std::string ret("\n"); char buf[256]; snprintf(buf, 256, "[%g %g %g %g]\n", static_cast(i.x), static_cast(j.x), static_cast(k.x), static_cast(p.x)); ret += buf; snprintf(buf, 256, "[%g %g %g %g]\n", static_cast(i.y), static_cast(j.y), static_cast(k.y), static_cast(p.y)); ret += buf; snprintf(buf, 256, "[%g %g %g %g]\n", static_cast(i.z), static_cast(j.z), static_cast(k.z), static_cast(p.z)); ret += buf; return ret; } //----------------------------------------------------------------- static std::string getDebugString(Vector const &v) { char buf[256]; snprintf(buf, 256, "[%g %g %g]", static_cast(v.x), static_cast(v.y), static_cast(v.z)); return std::string(buf); } //----------------------------------------------------------------- ConsoleCommandParserObjvar::ConsoleCommandParserObjvar (void) : CommandParser ("objvar", 0, "...", "Objvar related commands.", 0) { createDelegateCommands (cmds); } //----------------------------------------------------------------- bool ConsoleCommandParserObjvar::performParsing (const NetworkId & userId, const StringVector_t & argv, const String_t & originalCommand, String_t & result, const CommandParser * node) { NOT_NULL (node); UNREF (userId); UNREF(originalCommand); //----------------------------------------------------------------- if (isAbbrev( argv [0], "set")) { NetworkId oid (Unicode::wideToNarrow (argv[1])); ServerObject* object = ServerWorld::findObjectByNetworkId(oid); if (object == NULL) { result += getErrorMessage (argv [0], ERR_INVALID_OBJECT); return true; } const Unicode::NarrowString &objvarName = Unicode::wideToNarrow(argv[2]); // can't dork around with the "resourceData" objvar on a resource container // or a manufacturing schematic or an incubator, since it contains resource // data for "imported" resources that *MUST* remain the same as the // corresponding objvar on every other resource container or a manufacturing // schematic that references that "imported" resource. if (objvarName == "power.resourceData") { const char *objectTemplateName = object->getObjectTemplateName(); if (objectTemplateName && (std::string(objectTemplateName) == "object/tangible/crafting/station/incubator_station.iff")) { result += Unicode::narrowToWide("You cannot set the \"resourceData\" objvar on an incubator\n"); return true; } } int const gameObjectType = object->getGameObjectType(); if (GameObjectTypes::isTypeOf(gameObjectType, SharedObjectTemplate::GOT_resource_container) || (gameObjectType == SharedObjectTemplate::GOT_data_manufacturing_schematic)) { std::string::size_type const pos = objvarName.rfind("resourceData"); if (pos == (objvarName.size() - sizeof("resourceData") + 1)) { result += Unicode::narrowToWide("You cannot set the \"resourceData\" objvar on a resource crate or a manufacturing schematic\n"); return true; } } if (!object->getObjVars().hasItem(objvarName)) { // create a new objvar, deduce type from argument string const Unicode::NarrowString &nString = Unicode::wideToNarrow(argv[3]); switch (getArgumentType(nString)) { case INT_ARGUMENT: object->setObjVarItem(objvarName, atoi(nString.c_str())); break; case REAL_ARGUMENT: object->setObjVarItem(objvarName, static_cast(atof(nString.c_str()))); break; case STRING_ARGUMENT: object->setObjVarItem(objvarName, argv[3]); break; default: break; } result += getErrorMessage(argv[0], ERR_SUCCESS); } else { // verify that the argument passed in is the same type as the objvar switch (object->getObjVars().getType(objvarName)) { case DynamicVariable::INT: { const Unicode::NarrowString &nString = Unicode::wideToNarrow(argv[3]); if (getArgumentType(nString) == INT_ARGUMENT) { object->setObjVarItem(objvarName, atoi(nString.c_str())); result += getErrorMessage(argv[0], ERR_SUCCESS); } else result += getErrorMessage(argv[0], ERR_INVALID_INT_OBJVAR); } break; case DynamicVariable::INT_ARRAY: result += getErrorMessage(argv[0], ERR_CMD_NOT_FOUND); break; case DynamicVariable::REAL: { const Unicode::NarrowString &nString = Unicode::wideToNarrow(argv[3]); if (getArgumentType(nString) == REAL_ARGUMENT) { object->setObjVarItem(objvarName, static_cast(atof(nString.c_str()))); result += getErrorMessage(argv[0], ERR_SUCCESS); } else result += getErrorMessage(argv[0], ERR_INVALID_REAL_OBJVAR); } break; case DynamicVariable::REAL_ARRAY: result += getErrorMessage(argv[0], ERR_CMD_NOT_FOUND); break; case DynamicVariable::STRING: { object->setObjVarItem(objvarName, argv[3]); result += getErrorMessage(argv[0], ERR_SUCCESS); } break; case DynamicVariable::STRING_ARRAY: result += getErrorMessage(argv[0], ERR_CMD_NOT_FOUND); break; case DynamicVariable::NETWORK_ID: case DynamicVariable::NETWORK_ID_ARRAY: case DynamicVariable::LOCATION: case DynamicVariable::LOCATION_ARRAY: case DynamicVariable::STRING_ID: case DynamicVariable::STRING_ID_ARRAY: case DynamicVariable::TRANSFORM: case DynamicVariable::TRANSFORM_ARRAY: case DynamicVariable::VECTOR: case DynamicVariable::VECTOR_ARRAY: result += getErrorMessage(argv[0], ERR_CMD_NOT_FOUND); break; case DynamicVariable::LIST: result += getErrorMessage(argv[0], ERR_LIST_OBJVAR_NOT_SUPPORTED); break; } } } //----------------------------------------------------------------- else if (isAbbrev( argv [0], "setlist")) { // This is now a no-op, but left in to avoid breaking the god client // NetworkId oid (Unicode::wideToNarrow (argv[1])); // ServerObject* object = ServerWorld::findObjectByNetworkId(oid); // if (object == NULL) // { // result += getErrorMessage (argv [0], ERR_INVALID_OBJECT); // return true; // } // const Unicode::NarrowString &listName = Unicode::wideToNarrow(argv[2]); // object->addNestedObjVarList(listName); result += getErrorMessage(argv[0], ERR_SUCCESS); } //----------------------------------------------------------------- else if (isAbbrev( argv [0], "get")) { NetworkId oid (Unicode::wideToNarrow(argv[1])); ServerObject* object = ServerWorld::findObjectByNetworkId(oid); if (object == NULL) { result += getErrorMessage(argv[0], ERR_INVALID_OBJECT); return true; } std::string objvarName(Unicode::wideToNarrow(argv[2])); if (object->getObjVars().hasItem(objvarName)) { char buffer[32]; switch (object->getObjVars().getType(objvarName)) { case DynamicVariable::INT: { int value = 0; object->getObjVars().getItem(objvarName,value); IGNORE_RETURN(_itoa(value, buffer, 10)); result += Unicode::narrowToWide(buffer); } break; case DynamicVariable::INT_ARRAY: result += getErrorMessage(argv[0], ERR_CMD_NOT_FOUND); break; case DynamicVariable::REAL: { float value = 0; object->getObjVars().getItem(objvarName,value); sprintf(buffer, "%f", value); result += Unicode::narrowToWide(buffer); } break; case DynamicVariable::REAL_ARRAY: result += getErrorMessage(argv[0], ERR_CMD_NOT_FOUND); break; case DynamicVariable::STRING: { Unicode::String value; object->getObjVars().getItem(objvarName,value); result += value; } break; case DynamicVariable::STRING_ARRAY: result += getErrorMessage(argv[0], ERR_CMD_NOT_FOUND); break; case DynamicVariable::NETWORK_ID: case DynamicVariable::NETWORK_ID_ARRAY: case DynamicVariable::LOCATION: case DynamicVariable::LOCATION_ARRAY: case DynamicVariable::STRING_ID: case DynamicVariable::STRING_ID_ARRAY: case DynamicVariable::TRANSFORM: case DynamicVariable::TRANSFORM_ARRAY: case DynamicVariable::VECTOR: case DynamicVariable::VECTOR_ARRAY: result += getErrorMessage(argv[0], ERR_CMD_NOT_FOUND); break; case DynamicVariable::LIST: char buf[256]; sprintf (buf, "objvar list\n"); result += Unicode::narrowToWide(buf); listObjvars(DynamicVariableList::NestedList(object->getObjVars(),objvarName), result, 0, false); break; } } else { result += getErrorMessage(argv[0], ERR_INVALID_OBJVAR); } } //----------------------------------------------------------------- else if (isAbbrev(argv[0], "list")) { ServerObject * const userServerObject = ServerWorld::findObjectByNetworkId(userId); if (userServerObject != NULL) { NetworkId specifiedNetworkId; if (argv.size () > 1) { specifiedNetworkId = NetworkId(Unicode::wideToNarrow(argv[1])); } else { CreatureObject * const userCreatureObject = CreatureObject::asCreatureObject(userServerObject); if (userCreatureObject != NULL) { specifiedNetworkId = userCreatureObject->getLookAtTarget(); } } ServerObject * const specifiedServerObject = ServerWorld::findObjectByNetworkId(specifiedNetworkId); if (specifiedServerObject != NULL) { DynamicVariableList const & objVarList = specifiedServerObject->getObjVars(); FormattedString<1024> fs; result += Unicode::narrowToWide(fs.sprintf("objvar list for object %s, num %d\n", specifiedServerObject->getNetworkId().getValueString().c_str(), objVarList.size())); listObjvars(DynamicVariableList::NestedList(objVarList), result, 0, false); result += getErrorMessage(argv[0], ERR_SUCCESS); return true; } } result += getErrorMessage (argv [0], ERR_INVALID_OBJECT); } // ---------------------------------------------------------------------- else if (isAbbrev(argv[0], "listWithPacking")) { NetworkId oid = NetworkId(Unicode::wideToNarrow(argv[1])); ServerObject* object = ServerWorld::findObjectByNetworkId(oid); if (object == NULL) { result += getErrorMessage (argv [0], ERR_INVALID_OBJECT); return true; } char buf[256]; sprintf (buf, "objvar list\n"); result += Unicode::narrowToWide(buf); listObjvars(DynamicVariableList::NestedList(object->getObjVars()), result, 0, true); result += getErrorMessage(argv[0], ERR_SUCCESS); } //----------------------------------------------------------------- else if (isAbbrev(argv[0], "remove")) { NetworkId oid = NetworkId(Unicode::wideToNarrow(argv[1])); ServerObject* object = ServerWorld::findObjectByNetworkId(oid); if (object == NULL) { result += getErrorMessage (argv [0], ERR_INVALID_OBJECT); return true; } const Unicode::NarrowString &objvarName = Unicode::wideToNarrow(argv[2]); // can't dork around with the "resourceData" objvar on a resource container // or a manufacturing schematic or an incubator, since it contains resource // data for "imported" resources that *MUST* remain the same as the // corresponding objvar on every other resource container or a manufacturing // schematic that references that "imported" resource. if (objvarName == "power.resourceData") { const char *objectTemplateName = object->getObjectTemplateName(); if (objectTemplateName && (std::string(objectTemplateName) == "object/tangible/crafting/station/incubator_station.iff")) { result += Unicode::narrowToWide("You cannot remove the \"resourceData\" objvar on an incubator\n"); return true; } } int const gameObjectType = object->getGameObjectType(); if (GameObjectTypes::isTypeOf(gameObjectType, SharedObjectTemplate::GOT_resource_container) || (gameObjectType == SharedObjectTemplate::GOT_data_manufacturing_schematic)) { std::string::size_type const pos = objvarName.rfind("resourceData"); if (pos == (objvarName.size() - sizeof("resourceData") + 1)) { result += Unicode::narrowToWide("You cannot remove the \"resourceData\" objvar on a resource crate or a manufacturing schematic\n"); return true; } } object->removeObjVarItem(objvarName); result += getErrorMessage(argv[0], ERR_SUCCESS); } //----------------------------------------------------------------- else { result += getErrorMessage(argv[0], ERR_NO_HANDLER); } return true; } // ConsoleCommandParserObjvar::performParsing //----------------------------------------------------------------- /** * Determines the data type of an argument string. * * @param arg the string to analize * * @return INT_ARGUMENT if the string is all digits, * REAL_ARGUMENT if the string is all digits plus one '.', * STRING_ARGUMENT for everthing else */ int ConsoleCommandParserObjvar::getArgumentType(const Unicode::NarrowString &arg) const { bool foundDecimal = false; size_t const count = arg.size(); for (size_t i = 0; i < count; ++i) { if (!isdigit(arg[i])) { if ((i == 0) && (arg[i] == '-') && (count > 1)) continue; if (arg[i] != '.' || foundDecimal) return STRING_ARGUMENT; foundDecimal = true; } } if (foundDecimal) return REAL_ARGUMENT; return INT_ARGUMENT; } // ConsoleCommandParserObjvar::getArgumentType //----------------------------------------------------------------- /** * Prints out to a string all the objvars in an objvar list. * * @param objvarList the list to print * @param result string to print the list to * @param tabCount how many tabs to print before the data */ void ConsoleCommandParserObjvar::listObjvars(const DynamicVariableList::NestedList &objvarList, String_t &result, int tabCount, bool withPackingData) { static const String_t space = Unicode::narrowToWide(" "); static const String_t spaces = Unicode::narrowToWide(" "); static const String_t newline = Unicode::narrowToWide("\n"); static const String_t tabs = Unicode::narrowToWide("\t"); static const String_t islist = Unicode::narrowToWide("\n"); char buffer[32]; for (DynamicVariableList::NestedList::const_iterator objVar(objvarList.begin()); objVar!=objvarList.end(); ++objVar) { // pad the objvar for (int j = 0; j < tabCount; ++j) result += spaces; // print the name result += Unicode::narrowToWide(objVar.getName()); result += tabs; if (withPackingData) { char buffer[100]; sprintf(buffer,"%i",objVar.getPackedPosition()); result += Unicode::narrowToWide(std::string(buffer)); result += tabs; } // print the data switch (objVar.getType()) { case DynamicVariable::INT: { int value=0; objVar.getValue(value); IGNORE_RETURN(_itoa(value, buffer, 10)); result += Unicode::narrowToWide(buffer); result += newline; } break; case DynamicVariable::INT_ARRAY: { std::vector value; objVar.getValue(value); std::string text = "["; size_t count = value.size(); for (size_t j = 0; j < count; ++j) { IGNORE_RETURN(_itoa(value[j], buffer, 10)); text += buffer; if (j + 1 < count) text += ", "; } text += "]\n"; result += Unicode::narrowToWide(text); } break; case DynamicVariable::REAL: { real value = 0; objVar.getValue(value); sprintf(buffer, "%f\n", value); result += Unicode::narrowToWide(buffer); } break; case DynamicVariable::REAL_ARRAY: { std::vector value; objVar.getValue(value); std::string text = "["; size_t count = value.size(); for (size_t j = 0; j < count; ++j) { sprintf(buffer, "%f", value[j]); text += buffer; if (j + 1 < count) text += ", "; } text += "]\n"; result += Unicode::narrowToWide(text); } break; case DynamicVariable::STRING: { Unicode::String value; objVar.getValue(value); result += value; result += newline; } break; case DynamicVariable::STRING_ARRAY: { std::vector value; objVar.getValue(value); int k; int nameLength = objVar.getName().size(); result += Unicode::narrowToWide("[\n"); size_t count = value.size(); for (size_t j = 0; j < count; ++j) { for (k = 0; k < tabCount; ++k) result += spaces; for (k = 0; k < nameLength; ++k) result += space; result += tabs; result += value[j]; result += newline; } for (k = 0; k < tabCount; ++k) result += spaces; for (k = 0; k < nameLength; ++k) result += space; result += tabs; result += Unicode::narrowToWide("]\n"); } break; case DynamicVariable::NETWORK_ID: { NetworkId value; objVar.getValue(value); result += Unicode::narrowToWide("(NetworkId)"); result += Unicode::narrowToWide(value.getValueString()); result += newline; } break; case DynamicVariable::NETWORK_ID_ARRAY: { std::vector value; objVar.getValue(value); std::string text = "(NetworkId)["; size_t count = value.size(); for (size_t j = 0; j < count; ++j) { text += value[j].getValueString(); if (j + 1 < count) text += ", "; } text += "]\n"; result += Unicode::narrowToWide(text); } break; case DynamicVariable::LOCATION: { DynamicVariableLocationData value; objVar.getValue(value); result += Unicode::narrowToWide("(x="); sprintf(buffer, "%f", value.pos.x); result += Unicode::narrowToWide(buffer); result += Unicode::narrowToWide(", y="); sprintf(buffer, "%f", value.pos.y); result += Unicode::narrowToWide(buffer); result += Unicode::narrowToWide(", z="); sprintf(buffer, "%f", value.pos.z); result += Unicode::narrowToWide(buffer); result += Unicode::narrowToWide(", scene="); result += Unicode::narrowToWide(value.scene); result += Unicode::narrowToWide(", cell="); result += Unicode::narrowToWide(value.cell.getValueString()); result += Unicode::narrowToWide(")\n"); } break; case DynamicVariable::LOCATION_ARRAY: { std::vector value; objVar.getValue(value); int k; int nameLength = objVar.getName().size(); result += Unicode::narrowToWide("[\n"); size_t count = value.size(); for (size_t j = 0; j < count; ++j) { for (k = 0; k < tabCount; ++k) result += spaces; for (k = 0; k < nameLength; ++k) result += space; result += tabs; result += Unicode::narrowToWide("(x="); sprintf(buffer, "%f", value[j].pos.x); result += Unicode::narrowToWide(buffer); result += Unicode::narrowToWide(", y="); sprintf(buffer, "%f", value[j].pos.y); result += Unicode::narrowToWide(buffer); result += Unicode::narrowToWide(", z="); sprintf(buffer, "%f", value[j].pos.z); result += Unicode::narrowToWide(buffer); result += Unicode::narrowToWide(", scene="); result += Unicode::narrowToWide(value[j].scene); result += Unicode::narrowToWide(", cell="); result += Unicode::narrowToWide(value[j].cell.getValueString()); result += Unicode::narrowToWide(")\n"); } for (k = 0; k < tabCount; ++k) result += spaces; for (k = 0; k < nameLength; ++k) result += space; result += tabs; result += Unicode::narrowToWide("]\n"); } break; case DynamicVariable::LIST: result += islist; listObjvars(objVar.getNestedList(), result, tabCount + 1, withPackingData); break; case DynamicVariable::STRING_ID: { StringId value; objVar.getValue(value); result += Unicode::narrowToWide("(StringId)"); result += Unicode::narrowToWide(value.getDebugString()); result += newline; } break; case DynamicVariable::STRING_ID_ARRAY: { std::vector value; objVar.getValue(value); std::string text = "(StringId)["; size_t count = value.size(); for (size_t j = 0; j < count; ++j) { text += value[j].getDebugString(); if (j + 1 < count) text += ", "; } text += "]\n"; result += Unicode::narrowToWide(text); } break; case DynamicVariable::TRANSFORM: { Transform value; objVar.getValue(value); result += Unicode::narrowToWide("(Transform)"); result += Unicode::narrowToWide(getDebugString(value)); result += newline; } break; case DynamicVariable::TRANSFORM_ARRAY: { std::vector value; objVar.getValue(value); std::string text = "(Transform)["; size_t count = value.size(); for (size_t j = 0; j < count; ++j) { text += getDebugString(value[j]); if (j + 1 < count) text += ", "; } text += "]\n"; result += Unicode::narrowToWide(text); } break; case DynamicVariable::VECTOR: { Vector value; objVar.getValue(value); result += Unicode::narrowToWide("(Vector)"); result += Unicode::narrowToWide(getDebugString(value)); result += newline; } break; case DynamicVariable::VECTOR_ARRAY: { std::vector value; objVar.getValue(value); std::string text = "(Vector)["; size_t count = value.size(); for (size_t j = 0; j < count; ++j) { text += getDebugString(value[j]); if (j + 1 < count) text += ", "; } text += "]\n"; result += Unicode::narrowToWide(text); } break; } } } // ConsoleCommandParserObjvar::listObjvars // ======================================================================