// ====================================================================== // // ScriptMethodsPlayerAccount.cpp // copyright (c) 2001 Sony Online Entertainment // // ====================================================================== #include "serverScript/FirstServerScript.h" #include "serverScript/JavaLibrary.h" #include "serverGame/Chat.h" #include "serverGame/ConfigServerGame.h" #include "serverGame/ContainerInterface.h" #include "serverGame/CreatureObject.h" #include "serverGame/GameServer.h" #include "serverGame/MessageToQueue.h" #include "serverGame/NameManager.h" #include "serverGame/PlayerCreationManagerServer.h" #include "serverGame/PlayerCreatureController.h" #include "serverGame/PlayerObject.h" #include "serverGame/ServerCreatureObjectTemplate.h" #include "serverNetworkMessages/CentralGameServerMessages.h" #include "serverNetworkMessages/RenameCharacterMessage.h" #include "serverScript/ScriptParameters.h" #include "sharedFoundation/ConstCharCrcLowerString.h" #include "sharedLog/Log.h" #include "sharedNetworkMessages/GenericValueTypeMessage.h" #include "sharedNetworkMessages/NameErrors.h" #include "serverNetworkMessages/TransferRequestMoveValidation.h" #include "serverNetworkMessages/VerifyAndLockName.h" #include "serverScript/GameScriptObject.h" #include "sharedObject/ObjectTemplateList.h" #include "sharedObject/SlotId.h" #include "sharedObject/SlotIdManager.h" #include "sharedObject/SlottedContainer.h" #include "sharedUtility/DataTableManager.h" #include "sharedUtility/DataTable.h" #include "serverUtility/FreeCtsDataTable.h" #include "UnicodeUtils.h" #include using namespace JNIWrappersNamespace; // ====================================================================== // ScriptMethodsPlayerAccountNamespace // ====================================================================== namespace ScriptMethodsPlayerAccountNamespace { bool install(); jlong JNICALL getPlayerObject(JNIEnv *env, jobject self, jlong creature); jboolean JNICALL isIgnoring(JNIEnv *env, jobject self, jlong player, jstring who); jboolean JNICALL adjustLotCount(JNIEnv *env, jobject self, jlong player, jint adjustment); jint JNICALL getAccountNumLots(JNIEnv *env, jobject self, jlong player); jint JNICALL getGameFeatureBits(JNIEnv *env, jobject self, jlong player); jint JNICALL getSubscriptionFeatureBits(JNIEnv *env, jobject self, jlong player); jboolean JNICALL isUsingAdminLogin(JNIEnv *env, jobject self, jlong player); jboolean JNICALL isWarden(JNIEnv *env, jobject self, jlong player); jobject JNICALL getAccountTimeData(JNIEnv * env, jobject self, jlong target); jint JNICALL getPlayerLastLoginTime(JNIEnv *env, jobject self, jlong player); jboolean JNICALL isFreeTrialAccount(JNIEnv *env, jobject self, jlong player); jboolean JNICALL setCompletedTutorial(JNIEnv *env, jobject self, jlong player, jboolean value); void JNICALL logActivity(JNIEnv *env, jobject self, jlong player, jint activityType); jboolean JNICALL isAccountQualifiedForHousePackup(JNIEnv *env, jobject self, jlong target); jobject JNICALL getCharacterCtsHistory(JNIEnv * env, jobject self, jlong player); jobjectArray JNICALL getCharacterRetroactiveCtsObjvars(JNIEnv * env, jobject self, jlong player); jobjectArray JNICALL qualifyForFreeCts(JNIEnv *env, jobject self, jlong player); void JNICALL validateFreeCts(JNIEnv *env, jobject self, jlong player, jstring destinationGalaxy, jstring destinationCharacterName); void JNICALL performFreeCts(JNIEnv *env, jobject self, jlong player, jstring destinationGalaxy, jstring destinationCharacterName); void JNICALL validateCts(JNIEnv *env, jobject self, jlong player, jstring destinationGalaxy, jstring destinationCharacterName); void JNICALL performCts(JNIEnv *env, jobject self, jlong player, jstring destinationGalaxy, jstring destinationCharacterName); void JNICALL validateRenameCharacter(JNIEnv *env, jobject self, jlong player, jstring newName); void JNICALL renameCharacterReleaseNameReservation(JNIEnv *env, jobject self, jlong player); void JNICALL renameCharacter(JNIEnv *env, jobject self, jlong player, jstring newName); jint JNICALL getPlayerStationId(JNIEnv *env, jobject self, jlong player); } //======================================================================== // install //======================================================================== bool ScriptMethodsPlayerAccountNamespace::install() { const JNINativeMethod NATIVES[] = { #define JF(a,b,c) {a,b,(void*)(ScriptMethodsPlayerAccountNamespace::c)} JF("_getPlayerObject", "(J)J", getPlayerObject), JF("_isIgnoring", "(JLjava/lang/String;)Z", isIgnoring), JF("_adjustLotCount", "(JI)Z", adjustLotCount), JF("_getAccountNumLots", "(J)I", getAccountNumLots), JF("_getGameFeatureBits", "(J)I", getGameFeatureBits), JF("_getSubscriptionFeatureBits", "(J)I", getSubscriptionFeatureBits), JF("_isUsingAdminLogin", "(J)Z", isUsingAdminLogin), JF("_isWarden", "(J)Z", isWarden), JF("_getAccountTimeData", "(J)Lscript/dictionary;", getAccountTimeData), JF("_getPlayerLastLoginTime", "(J)I", getPlayerLastLoginTime), JF("_isFreeTrialAccount", "(J)Z", isFreeTrialAccount), JF("_setCompletedTutorial", "(JZ)Z", setCompletedTutorial), JF("__logActivity", "(JI)V", logActivity), JF("_isAccountQualifiedForHousePackup", "(J)Z", isAccountQualifiedForHousePackup), JF("_getCharacterCtsHistory", "(J)Lscript/dictionary;", getCharacterCtsHistory), JF("_getCharacterRetroactiveCtsObjvars", "(J)[Lscript/dictionary;", getCharacterRetroactiveCtsObjvars), JF("_qualifyForFreeCts", "(J)[Ljava/lang/String;", qualifyForFreeCts), JF("_validateFreeCts", "(JLjava/lang/String;Ljava/lang/String;)V", validateFreeCts), JF("_performFreeCts", "(JLjava/lang/String;Ljava/lang/String;)V", performFreeCts), JF("_validateCts", "(JLjava/lang/String;Ljava/lang/String;)V", validateCts), JF("_performCts", "(JLjava/lang/String;Ljava/lang/String;)V", performCts), JF("_validateRenameCharacter", "(JLjava/lang/String;)V", validateRenameCharacter), JF("_renameCharacterReleaseNameReservation", "(J)V", renameCharacterReleaseNameReservation), JF("_renameCharacter", "(JLjava/lang/String;)V", renameCharacter), JF("_getPlayerStationId", "(J)I", getPlayerStationId), }; return JavaLibrary::registerNatives(NATIVES, sizeof(NATIVES)/sizeof(NATIVES[0])); } // ====================================================================== // Methods for dealing with PlayerObjects and (Station) account data jlong JNICALL ScriptMethodsPlayerAccountNamespace::getPlayerObject(JNIEnv *env, jobject self, jlong creature) { UNREF(self); NOT_NULL(env); jlong objId = 0; ServerObject * creatureServerObject = NULL; if (JavaLibrary::getObject(creature,creatureServerObject)) { SlotId slot = SlotIdManager::findSlotId(ConstCharCrcLowerString("ghost")); if (slot != SlotId::invalid) { SlottedContainer const * const slots = ContainerInterface::getSlottedContainer(*creatureServerObject); if (slots) { Container::ContainerErrorCode tmp = Container::CEC_Success; CachedNetworkId playerObjectId = slots->getObjectInSlot(slot, tmp); objId = playerObjectId.getValue(); } } } return objId; } // ---------------------------------------------------------------------- jboolean JNICALL ScriptMethodsPlayerAccountNamespace::isIgnoring(JNIEnv *env, jobject self, jlong player, jstring who) { PlayerObject *playerObject = 0; if (!JavaLibrary::getObject(player, playerObject)) { DEBUG_WARNING(true, ("JavaLibrary::isIgnoring: bad player object")); return JNI_FALSE; } std::string whoStr; if (!JavaLibrary::convert(JavaStringParam(who), whoStr)) { DEBUG_WARNING(true, ("JavaLibrary::isIgnoring: bad who string")); return JNI_FALSE; } if (playerObject->isIgnoring(whoStr)) return JNI_TRUE; return JNI_FALSE; } // ---------------------------------------------------------------------- jboolean JNICALL ScriptMethodsPlayerAccountNamespace::adjustLotCount(JNIEnv *env, jobject self, jlong player, jint adjustment) { PlayerObject *playerObject = 0; if (!JavaLibrary::getObject(player, playerObject)) { DEBUG_WARNING(true, ("JavaLibrary::adjustLotCount: bad player object")); return JNI_FALSE; } return playerObject->adjustLotCount(adjustment); } // ---------------------------------------------------------------------- jint JNICALL ScriptMethodsPlayerAccountNamespace::getAccountNumLots(JNIEnv *env, jobject self, jlong player) { PlayerObject *playerObject = 0; if (!JavaLibrary::getObject(player, playerObject)) { DEBUG_WARNING(true, ("JavaLibrary::getAccountNumLots: bad player object")); return 0; } return playerObject->getAccountNumLots(); } // ---------------------------------------------------------------------- jint JNICALL ScriptMethodsPlayerAccountNamespace::getGameFeatureBits(JNIEnv *env, jobject self, jlong player) { CreatureObject *playerObject = 0; if (!JavaLibrary::getObject(player, playerObject)) { DEBUG_WARNING(true, ("JavaLibrary::getGameFeatureBits: bad player object")); return 0; } if (!playerObject->getClient()) { DEBUG_WARNING(true, ("JavaLibrary::getGameFeatureBits: player object had no client")); return 0; } return playerObject->getClient()->getGameFeatures(); } // ---------------------------------------------------------------------- jint JNICALL ScriptMethodsPlayerAccountNamespace::getSubscriptionFeatureBits(JNIEnv *env, jobject self, jlong player) { CreatureObject *playerObject = 0; if (!JavaLibrary::getObject(player, playerObject)) { DEBUG_WARNING(true, ("JavaLibrary::GetSubscriptionFeatureBits: bad player object")); return 0; } if (!playerObject->getClient()) { DEBUG_WARNING(true, ("JavaLibrary::GetSubscriptionFeatureBits: player object had no client")); return 0; } return playerObject->getClient()->getSubscriptionFeatures(); } // ---------------------------------------------------------------------- /** * Returns info on how long a player has been playing the game. * * @param env Java environment * @param self class calling this function * @param target the id of the player * * @return a dictionary with the player's account time info: * "total_subscription_time" the total amount of time since the player first subscribed * "total_entitled_time" the total amount of time the player has been billed * "last_login_time" the amount of time passed since the player last logged in * "entitled_login_time" the amount of billing time since the player last logged in */ jobject JNICALL ScriptMethodsPlayerAccountNamespace::getAccountTimeData(JNIEnv * env, jobject self, jlong target) { const CreatureObject * creature = 0; if (!JavaLibrary::getObject(target, creature)) return 0; const PlayerObject * player = PlayerCreatureController::getPlayerObject( creature); if (player == NULL) return 0; const Client * client = creature->getClient(); if (client == NULL) return 0; // get the values that came from Platform int total_time = static_cast(client->getEntitlementTotalTime()); int entitled_time = static_cast(client->getEntitlementEntitledTime()); int login_time = static_cast(client->getEntitlementTotalTimeSinceLastLogin()); int entitled_login_time = static_cast(client->getEntitlementEntitledTimeSinceLastLogin()); // override with any global configuration specified values int temp = ConfigServerGame::getMinEntitledTime(); if ((temp >= 0) && (temp > entitled_time)) entitled_time = temp; // override with any manually created test values on the creature if (creature->getObjVars().getItem("_testVeteran.total_time", temp)) total_time = temp; if (creature->getObjVars().getItem("_testVeteran.entitled_time", temp)) entitled_time = temp; if (creature->getObjVars().getItem("_testVeteran.login_time", temp)) login_time = temp; if (creature->getObjVars().getItem("_testVeteran.entitled_login_time", temp)) entitled_login_time = temp; // don't return any information if all the values are 0 because it // indicates that Platform does not have the information available // at this time; we'll try again the next time the player logs in. if ((total_time == 0) && (entitled_time == 0) && (login_time == 0) && (entitled_login_time == 0)) return 0; LocalRefPtr dictionary = createNewObject(JavaLibrary::getClsDictionary(), JavaLibrary::getMidDictionary()); if (dictionary != LocalRef::cms_nullPtr) { callObjectMethod(*dictionary, JavaLibrary::getMidDictionaryPutInt(), JavaString("total_subscription_time").getValue(), total_time); callObjectMethod(*dictionary, JavaLibrary::getMidDictionaryPutInt(), JavaString("total_entitled_time").getValue(), entitled_time); callObjectMethod(*dictionary, JavaLibrary::getMidDictionaryPutInt(), JavaString("last_login_time").getValue(), login_time); callObjectMethod(*dictionary, JavaLibrary::getMidDictionaryPutInt(), JavaString("entitled_login_time").getValue(), entitled_login_time); if (env->ExceptionCheck()) { env->ExceptionDescribe(); return 0; } } return dictionary->getReturnValue(); } // JavaLibrary::getAccountTimeData // ---------------------------------------------------------------------- jint JNICALL ScriptMethodsPlayerAccountNamespace::getPlayerLastLoginTime(JNIEnv *env, jobject self, jlong player) { NetworkId playerId(player); return NameManager::getInstance().getPlayerLastLoginTime(playerId); } // ---------------------------------------------------------------------- jboolean JNICALL ScriptMethodsPlayerAccountNamespace::isUsingAdminLogin(JNIEnv *env, jobject self, jlong player) { CreatureObject *playerObject = 0; if (!JavaLibrary::getObject(player, playerObject)) { DEBUG_WARNING(true, ("JavaLibrary::isUsingAdminLogin: bad player object")); return false; } if (!playerObject->getClient()) { DEBUG_WARNING(true, ("JavaLibrary::isUsingAdminLogin: player object had no client")); return false; } return playerObject->getClient()->isUsingAdminLogin(); } // ---------------------------------------------------------------------- jboolean JNICALL ScriptMethodsPlayerAccountNamespace::isWarden(JNIEnv *env, jobject self, jlong player) { CreatureObject *creatureObject = 0; if (!JavaLibrary::getObject(player, creatureObject)) { DEBUG_WARNING(true, ("JavaLibrary::isWarden: bad creature object")); return false; } PlayerObject *playerObject = PlayerCreatureController::getPlayerObject(creatureObject); if (!playerObject) { DEBUG_WARNING(true, ("JavaLibrary::isWarden: creature object had no player object")); return false; } return playerObject->isWarden(); } // ---------------------------------------------------------------------- jboolean JNICALL ScriptMethodsPlayerAccountNamespace::isFreeTrialAccount(JNIEnv *env, jobject self, jlong player) { CreatureObject *playerObject = 0; if (!JavaLibrary::getObject(player, playerObject)) { DEBUG_WARNING(true, ("JavaLibrary::isFreeTrialAccount: bad player object")); return false; } if (!playerObject->getClient()) { DEBUG_WARNING(true, ("JavaLibrary::isFreeTrialAccount: player object had no client")); return false; } return playerObject->getClient()->isFreeTrialAccount(); } // ---------------------------------------------------------------------- jboolean JNICALL ScriptMethodsPlayerAccountNamespace::setCompletedTutorial(JNIEnv *env, jobject self, jlong player, jboolean value) { CreatureObject *playerObject = 0; if (!JavaLibrary::getObject(player, playerObject)) { DEBUG_WARNING(true, ("JavaLibrary::setCompletedTutorial: bad player object")); return false; } if (!playerObject->getClient()) { DEBUG_WARNING(true, ("JavaLibrary::setCompletedTutorial: player object had no client")); return false; } if (playerObject->getClient()->isFreeTrialAccount()) { DEBUG_WARNING(true, ("JavaLibrary::setCompletedTutorial: client is from a free trial and CANNOT have completed tutorial bit set")); return false; } const unsigned int stationId = playerObject->getClient()->getStationId(); LOG("CustomerService", ("Setting tutorial bit to %s for stationId %i\n", (value) ? "true" : "false", stationId)); GenericValueTypeMessage< std::pair > const updateTutorial("LoginToggleCompletedTutorial", std::pair(stationId, value)); GameServer::getInstance().sendToCentralServer(updateTutorial); return true; } // ---------------------------------------------------------------------- void JNICALL ScriptMethodsPlayerAccountNamespace::logActivity(JNIEnv *env, jobject self, jlong player, jint activityType) { UNREF(self); CreatureObject * creatureObject = 0; if (!JavaLibrary::getObject(player, creatureObject)) return; PlayerObject * playerObject = PlayerCreatureController::getPlayerObject(creatureObject); if (playerObject) playerObject->addSessionActivity(static_cast(activityType)); } // ---------------------------------------------------------------------- jboolean JNICALL ScriptMethodsPlayerAccountNamespace::isAccountQualifiedForHousePackup(JNIEnv *env, jobject self, jlong target) { UNREF(self); NOT_NULL(env); static std::unordered_set accountsQualifiedForHousePackup; if (accountsQualifiedForHousePackup.empty()) { DataTable * table = DataTableManager::getTable(ConfigServerGame::getHousePackupAccountListDataTableName(), true); if (table) { int const columnId = table->findColumnNumber("stationId"); if (columnId >= 0) { int const numRows = table->getNumRows(); for (int i = 0; i < numRows; ++i) { IGNORE_RETURN(accountsQualifiedForHousePackup.insert(static_cast(table->getIntValue(columnId, i)))); } } DataTableManager::close(ConfigServerGame::getHousePackupAccountListDataTableName()); } } return (accountsQualifiedForHousePackup.count(static_cast(NameManager::getInstance().getPlayerStationId(NetworkId(static_cast(target))))) >= 1); } /** * Gets the CTS history of the specified character * * @returns a dictionary that contains the following data in paralled arrays * with the oldest CTS transaction first and the newest CTS transaction last * * @returns null if the character doesn't have any CTS history * * string[] character_name full name of the source character * string[] cluster_name name of the source cluster * int[] transfer_time calendar time of the transfer */ jobject JNICALL ScriptMethodsPlayerAccountNamespace::getCharacterCtsHistory(JNIEnv * env, jobject self, jlong player) { CreatureObject const * playerObject = NULL; if (!JavaLibrary::getObject(player, playerObject)) { DEBUG_WARNING(true, ("JavaLibrary::getCharacterCtsHistory: bad player object")); return 0; } if (!playerObject->getObjVars().hasItem("ctsHistory")) return 0; // we need to return the CTS history ordered by transfer time std::multimap > orderedCtsHistory; DynamicVariableList::NestedList const ctsTransactions(playerObject->getObjVars(), "ctsHistory"); for (DynamicVariableList::NestedList::const_iterator i = ctsTransactions.begin(); i != ctsTransactions.end(); ++i) { Unicode::String ctsTransactionDetail; if (i.getValue(ctsTransactionDetail)) { Unicode::UnicodeStringVector tokens; if (Unicode::tokenize(ctsTransactionDetail, tokens, NULL, NULL) && (tokens.size() >= 4)) { Unicode::String * characterName = new Unicode::String(); for (size_t i = 3, j = tokens.size(); i < j; ++i) { if (!characterName->empty()) *characterName += Unicode::narrowToWide(" "); *characterName += tokens[i]; } IGNORE_RETURN(orderedCtsHistory.insert(std::make_pair(atoi(Unicode::wideToNarrow(tokens[0]).c_str()), std::make_pair(characterName, new Unicode::String(tokens[1]))))); } } } if (orderedCtsHistory.empty()) return 0; std::vector * sourceCharacterName = new std::vector; std::vector * sourceClusterName = new std::vector; std::vector * transferTime = new std::vector; for (std::multimap >::const_iterator iter = orderedCtsHistory.begin(); iter != orderedCtsHistory.end(); ++iter) { transferTime->push_back(iter->first); sourceCharacterName->push_back(iter->second.first); sourceClusterName->push_back(iter->second.second); } ScriptParams params; params.addParam(*sourceCharacterName, "character_name", true); params.addParam(*sourceClusterName, "cluster_name", true); params.addParam(*transferTime, "transfer_time", true); JavaDictionaryPtr dictionary; JavaLibrary::instance()->convert(params, dictionary); return dictionary->getReturnValue(); } // JavaLibrary::requestJedi /** * Gets the retroactive CTS objvars history of the specified character * * @returns an array of dictionaries each of which contains the retroactive CTS objvars * for the particular CTS source character that this character at one time transferred from * with the oldest CTS transaction first and the newest CTS transaction last * * @returns null if the character doesn't have any retroactive CTS objvars history */ jobjectArray JNICALL ScriptMethodsPlayerAccountNamespace::getCharacterRetroactiveCtsObjvars(JNIEnv * env, jobject self, jlong player) { std::vector > const *> const & characterRetroactiveCtsObjvars = GameServer::getRetroactiveCtsHistoryObjvars(NetworkId(static_cast(player))); if (characterRetroactiveCtsObjvars.empty()) return NULL; LocalObjectArrayRefPtr results = createNewObjectArray(characterRetroactiveCtsObjvars.size(), JavaLibrary::getClsDictionary()); for (size_t i = 0, size = characterRetroactiveCtsObjvars.size(); i < size; ++i) { bool addedAnything = false; ScriptParams params; if (characterRetroactiveCtsObjvars[i] && !characterRetroactiveCtsObjvars[i]->empty()) { for (std::vector >::const_iterator iterObjvar = characterRetroactiveCtsObjvars[i]->begin(); iterObjvar != characterRetroactiveCtsObjvars[i]->end(); ++iterObjvar) { // can only handle INT (type 0) and INT_ARRAY (type 1) objvar type at this time if (iterObjvar->second.getType() == DynamicVariable::INT) { int iValue; iterObjvar->second.get(iValue); params.addParam(iValue, iterObjvar->first); addedAnything = true; } else if (iterObjvar->second.getType() == DynamicVariable::INT_ARRAY) { // iaValue will be owned and deleted by params std::vector * iaValue = new std::vector(); iterObjvar->second.get(*iaValue); params.addParam(*iaValue, iterObjvar->first, true); addedAnything = true; } } } if (!addedAnything) { setObjectArrayElement(*results, i, *JavaDictionary::cms_nullPtr); } else { JavaDictionaryPtr dictionary; JavaLibrary::instance()->convert(params, dictionary); setObjectArrayElement(*results, i, *dictionary); } } return results->getReturnValue(); } /** * Checks to see if the specified character qualifies for free CTS * * @returns an array of strings containing the galaxies to which this character can transfer for free */ jobjectArray JNICALL ScriptMethodsPlayerAccountNamespace::qualifyForFreeCts(JNIEnv * /*env*/, jobject /*self*/, jlong player) { time_t const characterCreateTime = static_cast(NameManager::getInstance().getPlayerCreateTime(NetworkId(player))); FreeCtsDataTable::FreeCtsInfo const * freeCtsInfo = FreeCtsDataTable::getFreeCtsInfoForCharacter(characterCreateTime, GameServer::getInstance().getClusterName(), false); // see if we can/should bypass the free CTS time restriction if (!freeCtsInfo && ConfigServerGame::getAllowIgnoreFreeCtsTimeRestriction()) { CreatureObject const * playerObject = NULL; if (JavaLibrary::getObject(player, playerObject) && playerObject && playerObject->getClient() && playerObject->getClient()->isGod()) { freeCtsInfo = FreeCtsDataTable::getFreeCtsInfoForCharacter(characterCreateTime, GameServer::getInstance().getClusterName(), true); if (freeCtsInfo) { Chat::sendSystemMessage(*playerObject, Unicode::narrowToWide("Bypassing free CTS time restriction for GOD MODE!!!"), Unicode::emptyString); } } } if (!freeCtsInfo || freeCtsInfo->targetCluster.empty()) return NULL; LocalObjectArrayRefPtr valueArray = createNewObjectArray(freeCtsInfo->targetCluster.size(), JavaLibrary::getClsString()); int i = 0; for (std::map::const_iterator iter = freeCtsInfo->targetCluster.begin(); iter != freeCtsInfo->targetCluster.end(); ++iter) { JavaString jval(iter->second); setObjectArrayElement(*valueArray, i++, jval); } return valueArray->getReturnValue(); } /** * Validate the free CTS information and messageTo back to the object to indicate status of the validation */ void JNICALL ScriptMethodsPlayerAccountNamespace::validateFreeCts(JNIEnv * /*env*/, jobject /*self*/, jlong player, jstring destinationGalaxy, jstring destinationCharacterName) { CreatureObject const * creatureObject = NULL; if (!JavaLibrary::getObject(player, creatureObject) || !creatureObject) { DEBUG_WARNING(true, ("JavaLibrary::validateFreeCts: bad CreatureObject")); return; } PlayerObject const * const playerObject = PlayerCreatureController::getPlayerObject(creatureObject); if (!playerObject) { DEBUG_WARNING(true, ("JavaLibrary::validateFreeCts: bad PlayerObject")); return; } std::string destinationGalaxyString; JavaStringParam temp1(destinationGalaxy); if (!JavaLibrary::convert(temp1, destinationGalaxyString)) { DEBUG_WARNING(true, ("JavaLibrary::validateFreeCts: bad destinationGalaxy")); return; } std::string destinationCharacterNameString; JavaStringParam temp2(destinationCharacterName); if (!JavaLibrary::convert(temp2, destinationCharacterNameString)) { DEBUG_WARNING(true, ("JavaLibrary::validateFreeCts: bad destinationCharacterName")); return; } TransferRequestMoveValidation const trmv(TransferRequestMoveValidation::TRS_ingame_freects_command_validate, GameServer::getInstance().getProcessId(), playerObject->getStationId(), playerObject->getStationId(), GameServer::getInstance().getClusterName(), destinationGalaxyString, Unicode::wideToNarrow(creatureObject->getAssignedObjectName()), creatureObject->getNetworkId(), creatureObject->getTemplateCrc(), destinationCharacterNameString, std::string("en")); GameServer::getInstance().sendToCentralServer(trmv); } /** * Validate the free CTS information and initiate the transfer process if the validation passes, or * messageTo back to the object to indicate status of the validation if the validation fails */ void JNICALL ScriptMethodsPlayerAccountNamespace::performFreeCts(JNIEnv * /*env*/, jobject /*self*/, jlong player, jstring destinationGalaxy, jstring destinationCharacterName) { CreatureObject const * creatureObject = NULL; if (!JavaLibrary::getObject(player, creatureObject) || !creatureObject) { DEBUG_WARNING(true, ("JavaLibrary::performFreeCts: bad CreatureObject")); return; } PlayerObject const * const playerObject = PlayerCreatureController::getPlayerObject(creatureObject); if (!playerObject) { DEBUG_WARNING(true, ("JavaLibrary::performFreeCts: bad PlayerObject")); return; } std::string destinationGalaxyString; JavaStringParam temp1(destinationGalaxy); if (!JavaLibrary::convert(temp1, destinationGalaxyString)) { DEBUG_WARNING(true, ("JavaLibrary::performFreeCts: bad destinationGalaxy")); return; } std::string destinationCharacterNameString; JavaStringParam temp2(destinationCharacterName); if (!JavaLibrary::convert(temp2, destinationCharacterNameString)) { DEBUG_WARNING(true, ("JavaLibrary::performFreeCts: bad destinationCharacterName")); return; } TransferRequestMoveValidation const trmv(TransferRequestMoveValidation::TRS_ingame_freects_command_transfer, GameServer::getInstance().getProcessId(), playerObject->getStationId(), playerObject->getStationId(), GameServer::getInstance().getClusterName(), destinationGalaxyString, Unicode::wideToNarrow(creatureObject->getAssignedObjectName()), creatureObject->getNetworkId(), creatureObject->getTemplateCrc(), destinationCharacterNameString, std::string("en")); GameServer::getInstance().sendToCentralServer(trmv); } /** * Validate the CTS information and messageTo back to the object to indicate status of the validation */ void JNICALL ScriptMethodsPlayerAccountNamespace::validateCts(JNIEnv * /*env*/, jobject /*self*/, jlong player, jstring destinationGalaxy, jstring destinationCharacterName) { CreatureObject const * creatureObject = NULL; if (!JavaLibrary::getObject(player, creatureObject) || !creatureObject) { DEBUG_WARNING(true, ("JavaLibrary::validateCts: bad CreatureObject")); return; } PlayerObject const * const playerObject = PlayerCreatureController::getPlayerObject(creatureObject); if (!playerObject) { DEBUG_WARNING(true, ("JavaLibrary::validateCts: bad PlayerObject")); return; } std::string destinationGalaxyString; JavaStringParam temp1(destinationGalaxy); if (!JavaLibrary::convert(temp1, destinationGalaxyString)) { DEBUG_WARNING(true, ("JavaLibrary::validateCts: bad destinationGalaxy")); return; } std::string destinationCharacterNameString; JavaStringParam temp2(destinationCharacterName); if (!JavaLibrary::convert(temp2, destinationCharacterNameString)) { DEBUG_WARNING(true, ("JavaLibrary::validateCts: bad destinationCharacterName")); return; } TransferRequestMoveValidation const trmv(TransferRequestMoveValidation::TRS_ingame_cts_command_validate, GameServer::getInstance().getProcessId(), playerObject->getStationId(), playerObject->getStationId(), GameServer::getInstance().getClusterName(), destinationGalaxyString, Unicode::wideToNarrow(creatureObject->getAssignedObjectName()), creatureObject->getNetworkId(), creatureObject->getTemplateCrc(), destinationCharacterNameString, std::string("en")); GameServer::getInstance().sendToCentralServer(trmv); } /** * Validate the CTS information and initiate the transfer process if the validation passes, or * messageTo back to the object to indicate status of the validation if the validation fails */ void JNICALL ScriptMethodsPlayerAccountNamespace::performCts(JNIEnv * /*env*/, jobject /*self*/, jlong player, jstring destinationGalaxy, jstring destinationCharacterName) { CreatureObject const * creatureObject = NULL; if (!JavaLibrary::getObject(player, creatureObject) || !creatureObject) { DEBUG_WARNING(true, ("JavaLibrary::performCts: bad CreatureObject")); return; } PlayerObject const * const playerObject = PlayerCreatureController::getPlayerObject(creatureObject); if (!playerObject) { DEBUG_WARNING(true, ("JavaLibrary::performCts: bad PlayerObject")); return; } std::string destinationGalaxyString; JavaStringParam temp1(destinationGalaxy); if (!JavaLibrary::convert(temp1, destinationGalaxyString)) { DEBUG_WARNING(true, ("JavaLibrary::performCts: bad destinationGalaxy")); return; } std::string destinationCharacterNameString; JavaStringParam temp2(destinationCharacterName); if (!JavaLibrary::convert(temp2, destinationCharacterNameString)) { DEBUG_WARNING(true, ("JavaLibrary::performCts: bad destinationCharacterName")); return; } TransferRequestMoveValidation const trmv(TransferRequestMoveValidation::TRS_ingame_cts_command_transfer, GameServer::getInstance().getProcessId(), playerObject->getStationId(), playerObject->getStationId(), GameServer::getInstance().getClusterName(), destinationGalaxyString, Unicode::wideToNarrow(creatureObject->getAssignedObjectName()), creatureObject->getNetworkId(), creatureObject->getTemplateCrc(), destinationCharacterNameString, std::string("en")); GameServer::getInstance().sendToCentralServer(trmv); } /** * Validate the new character name for the rename operation and messageTo back to the object to indicate status of the validation */ void JNICALL ScriptMethodsPlayerAccountNamespace::validateRenameCharacter(JNIEnv *env, jobject self, jlong player, jstring newName) { CreatureObject const * creatureObject = NULL; if (!JavaLibrary::getObject(player, creatureObject) || !creatureObject) { DEBUG_WARNING(true, ("JavaLibrary::validateRenameCharacter: bad CreatureObject")); return; } PlayerObject const * const playerObject = PlayerCreatureController::getPlayerObject(creatureObject); if (!playerObject) { DEBUG_WARNING(true, ("JavaLibrary::validateRenameCharacter: bad PlayerObject")); return; } Unicode::String newNameString; JavaStringParam temp(newName); if (!JavaLibrary::convert(temp, newNameString)) { DEBUG_WARNING(true, ("JavaLibrary::validateRenameCharacter: bad newName")); return; } // if this is a last name change only, to validate that the last name is valid, // generate a random unique first name, and validate that with the new last name bool lastNameChangeOnly = false; static Unicode::String const delimiters(Unicode::narrowToWide(" ")); Unicode::UnicodeStringVector newNameTokens; if (!Unicode::tokenize(newNameString, newNameTokens, &delimiters, NULL)) newNameTokens.clear(); size_t const newNameTokensCount = newNameTokens.size(); if ((newNameTokensCount == 1) || (newNameTokensCount == 2)) { if (Unicode::caseInsensitiveCompare(creatureObject->getAssignedObjectFirstName(), newNameTokens[0])) { lastNameChangeOnly = true; // no last name specified, so validation passes if (newNameTokensCount == 1) { MessageToQueue::getInstance().sendMessageToJava(creatureObject->getNetworkId(), "renameCharacterNameValidationSuccess", std::vector(), 0, false); return; } else { const ObjectTemplate * const objectTemplate = ObjectTemplateList::fetch(creatureObject->getObjectTemplateName()); if (objectTemplate) { const ServerCreatureObjectTemplate * const creatureTemplate = dynamic_cast(objectTemplate); if (creatureTemplate) { Unicode::String const uniqueRandomName = NameManager::getInstance().generateUniqueRandomName(ConfigServerGame::getCharacterNameGeneratorDirectory(), creatureTemplate->getNameGeneratorType()); Unicode::UnicodeStringVector uniqueRandomNameTokens; if (!Unicode::tokenize(uniqueRandomName, uniqueRandomNameTokens, &delimiters, NULL)) uniqueRandomNameTokens.clear(); newNameString = ((uniqueRandomNameTokens.size() >= 1) ? uniqueRandomNameTokens[0] : delimiters) + delimiters + newNameTokens[1]; } } } } } else { ScriptParams params; params.addParam("@ui:name_declined_racially_inappropriate", "reason"); ScriptDictionaryPtr dictionary; GameScriptObject::makeScriptDictionary(params, dictionary); if (dictionary.get() != NULL) { dictionary->serialize(); MessageToQueue::getInstance().sendMessageToJava(creatureObject->getNetworkId(), "renameCharacterNameValidationFail", dictionary->getSerializedData(), 0, false); } return; } VerifyAndLockNameRequest const verifyRequest(playerObject->getStationId(), creatureObject->getNetworkId(), creatureObject->getObjectTemplateName(), newNameString, 0xFFFFFFFF); StringId const verifyResult = GameServer::getInstance().handleVerifyAndLockNameRequest(verifyRequest, false, !lastNameChangeOnly); if (verifyResult != NameErrors::nameApproved) { std::string const errorText(std::string("@") + verifyResult.getCanonicalRepresentation()); ScriptParams params; params.addParam(errorText.c_str(), "reason"); ScriptDictionaryPtr dictionary; GameScriptObject::makeScriptDictionary(params, dictionary); if (dictionary.get() != NULL) { dictionary->serialize(); MessageToQueue::getInstance().sendMessageToJava(creatureObject->getNetworkId(), "renameCharacterNameValidationFail", dictionary->getSerializedData(), 0, false); } } else if (lastNameChangeOnly) { // last name passes validation MessageToQueue::getInstance().sendMessageToJava(creatureObject->getNetworkId(), "renameCharacterNameValidationSuccess", std::vector(), 0, false); } else { // nothing to do here, as it means the request has been forwarded // to the DB server for additional verification, so when that // verification is complete, we'll send the response from there } } /** * Release the character name that had been reserved for renaming the specified character; the character * name is reserved during the character rename process, even if the name doesn't end up being used, * so we want to return the name back to the pool; just make sure you don't call this function during * the character rename process, or before the character rename process has completed */ void JNICALL ScriptMethodsPlayerAccountNamespace::renameCharacterReleaseNameReservation(JNIEnv *env, jobject self, jlong player) { CreatureObject const * creatureObject = NULL; if (!JavaLibrary::getObject(player, creatureObject) || !creatureObject) { DEBUG_WARNING(true, ("JavaLibrary::renameCharacterReleaseNameReservation: bad CreatureObject")); return; } PlayerObject const * const playerObject = PlayerCreatureController::getPlayerObject(creatureObject); if (!playerObject) { DEBUG_WARNING(true, ("JavaLibrary::renameCharacterReleaseNameReservation: bad PlayerObject")); return; } ReleaseNameMessage const rnm(playerObject->getStationId(), creatureObject->getNetworkId()); GameServer::getInstance().sendToDatabaseServer(rnm); } /** * submit request to rename character; the name is assumed to have already been validated with validateRenameCharacter() */ void JNICALL ScriptMethodsPlayerAccountNamespace::renameCharacter(JNIEnv *env, jobject self, jlong player, jstring newName) { CreatureObject const * creatureObject = NULL; if (!JavaLibrary::getObject(player, creatureObject) || !creatureObject) { DEBUG_WARNING(true, ("JavaLibrary::renameCharacter: bad CreatureObject")); return; } PlayerObject const * const playerObject = PlayerCreatureController::getPlayerObject(creatureObject); if (!playerObject) { DEBUG_WARNING(true, ("JavaLibrary::renameCharacter: bad PlayerObject")); return; } Unicode::String newNameString; JavaStringParam temp(newName); if (!JavaLibrary::convert(temp, newNameString)) { DEBUG_WARNING(true, ("JavaLibrary::renameCharacter: bad newName")); return; } PlayerCreationManagerServer::renamePlayer(static_cast(RenameCharacterMessageEx::RCMS_player_request), playerObject->getStationId(), creatureObject->getNetworkId(), newNameString, creatureObject->getAssignedObjectName(), NetworkId::cms_invalid); } // ---------------------------------------------------------------------- /** * Get the station id of the player. * * @param env Java environment * @param self class calling this function * @param player the id of the player * * @return the station id of the player */ jint JNICALL ScriptMethodsPlayerAccountNamespace::getPlayerStationId(JNIEnv *env, jobject self, jlong player) { UNREF(self); NOT_NULL(env); return NameManager::getInstance().getPlayerStationId(NetworkId(static_cast(player))); } // ======================================================================