mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-24 06:06:23 +00:00
feat(Core/DBC): Implement NamesProfanity and NamesReserved DBC (#14956)
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
--
|
||||
DROP TABLE IF EXISTS `namesreserved_dbc`;
|
||||
CREATE TABLE `namesreserved_dbc` (
|
||||
`ID` INT UNSIGNED NOT NULL,
|
||||
`Pattern` TINYTEXT NOT NULL,
|
||||
`LanguagueID` TINYINT NOT NULL,
|
||||
PRIMARY KEY (`ID`)
|
||||
);
|
||||
|
||||
DROP TABLE IF EXISTS `namesprofanity_dbc`;
|
||||
CREATE TABLE `namesprofanity_dbc` (
|
||||
`ID` INT UNSIGNED NOT NULL,
|
||||
`Pattern` TINYTEXT NOT NULL,
|
||||
`LanguagueID` TINYINT NOT NULL,
|
||||
PRIMARY KEY (`ID`)
|
||||
);
|
||||
@@ -626,6 +626,24 @@ RealmZone = 1
|
||||
|
||||
World.RealmAvailability = 1
|
||||
|
||||
#
|
||||
# StrictNames.Reserved
|
||||
# Description: Use the Reserved Filter from DBC.
|
||||
# Prevents Player, Pet & Charter names from containing reserved names.
|
||||
# Default: 1 - Enabled
|
||||
# 0 - Disabled
|
||||
|
||||
StrictNames.Reserved = 1
|
||||
|
||||
#
|
||||
# StrictNames.Profanity
|
||||
# Description: Use the Profanity Filter from DBC.
|
||||
# Prevents Player, Pet & Charter names from containing profanity.
|
||||
# Default: 1 - Enabled
|
||||
# 0 - Disabled
|
||||
|
||||
StrictNames.Profanity = 1
|
||||
|
||||
#
|
||||
# StrictPlayerNames
|
||||
# Description: Limit player name to language specific symbol set. Prevents character
|
||||
|
||||
@@ -121,6 +121,9 @@ MapDifficultyMap sMapDifficultyMap;
|
||||
|
||||
DBCStorage <MovieEntry> sMovieStore(MovieEntryfmt);
|
||||
|
||||
DBCStorage <NamesReservedEntry> sNamesReservedStore(NamesReservedfmt);
|
||||
DBCStorage <NamesProfanityEntry> sNamesProfanityStore(NamesProfanityfmt);
|
||||
|
||||
DBCStorage <OverrideSpellDataEntry> sOverrideSpellDataStore(OverrideSpellDatafmt);
|
||||
|
||||
DBCStorage <PowerDisplayEntry> sPowerDisplayStore(PowerDisplayfmt);
|
||||
@@ -330,6 +333,8 @@ void LoadDBCStores(const std::string& dataPath)
|
||||
LOAD_DBC(sMapStore, "Map.dbc", "map_dbc");
|
||||
LOAD_DBC(sMapDifficultyStore, "MapDifficulty.dbc", "mapdifficulty_dbc");
|
||||
LOAD_DBC(sMovieStore, "Movie.dbc", "movie_dbc");
|
||||
LOAD_DBC(sNamesReservedStore, "NamesReserved.dbc", "namesreserved_dbc");
|
||||
LOAD_DBC(sNamesProfanityStore, "NamesProfanity.dbc", "namesprofanity_dbc");
|
||||
LOAD_DBC(sOverrideSpellDataStore, "OverrideSpellData.dbc", "overridespelldata_dbc");
|
||||
LOAD_DBC(sPowerDisplayStore, "PowerDisplay.dbc", "powerdisplay_dbc");
|
||||
LOAD_DBC(sPvPDifficultyStore, "PvpDifficulty.dbc", "pvpdifficulty_dbc");
|
||||
|
||||
@@ -138,6 +138,8 @@ extern DBCStorage <MapEntry> sMapStore;
|
||||
//extern DBCStorage <MapDifficultyEntry> sMapDifficultyStore; -- use GetMapDifficultyData insteed
|
||||
extern MapDifficultyMap sMapDifficultyMap;
|
||||
extern DBCStorage <MovieEntry> sMovieStore;
|
||||
extern DBCStorage <NamesReservedEntry> sNamesReservedStore;
|
||||
extern DBCStorage <NamesProfanityEntry> sNamesProfanityStore;
|
||||
extern DBCStorage <OverrideSpellDataEntry> sOverrideSpellDataStore;
|
||||
extern DBCStorage <PowerDisplayEntry> sPowerDisplayStore;
|
||||
extern DBCStorage <QuestSortEntry> sQuestSortStore;
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "Config.h"
|
||||
#include "Containers.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "DBCStructure.h"
|
||||
#include "DisableMgr.h"
|
||||
#include "GameObjectAIFactory.h"
|
||||
#include "GameEventMgr.h"
|
||||
@@ -53,6 +54,7 @@
|
||||
#include "World.h"
|
||||
#include "StringConvert.h"
|
||||
#include "Tokenize.h"
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
ScriptMapMap sSpellScripts;
|
||||
ScriptMapMap sEventScripts;
|
||||
@@ -203,6 +205,62 @@ std::string ScriptInfo::GetDebugInfo() const
|
||||
return std::string(sz);
|
||||
}
|
||||
|
||||
/**
|
||||
* @name ReservedNames
|
||||
* @brief Checks NamesReserved.dbc for reserved names
|
||||
*
|
||||
* @param name Name to check for match in NamesReserved.dbc
|
||||
* @return true/false
|
||||
*/
|
||||
bool ReservedNames(std::wstring& name)
|
||||
{
|
||||
for (NamesReservedEntry const* reservedStore : sNamesReservedStore)
|
||||
{
|
||||
std::wstring PatternString;
|
||||
|
||||
Utf8toWStr(reservedStore->Pattern, PatternString);
|
||||
|
||||
boost::algorithm::replace_all(PatternString, "\\<", "");
|
||||
boost::algorithm::replace_all(PatternString, "\\>", "");
|
||||
|
||||
int stringCompare = name.compare(PatternString);
|
||||
if (stringCompare == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* @name ProfanityNames
|
||||
* @brief Checks NamesProfanity.dbc for reserved names
|
||||
*
|
||||
* @param name Name to check for match in NamesProfanity.dbc
|
||||
* @return true/false
|
||||
*/
|
||||
bool ProfanityNames(std::wstring& name)
|
||||
{
|
||||
for (NamesProfanityEntry const* profanityStore : sNamesProfanityStore)
|
||||
{
|
||||
std::wstring PatternString;
|
||||
|
||||
Utf8toWStr(profanityStore->Pattern, PatternString);
|
||||
|
||||
boost::algorithm::replace_all(PatternString, "\\<", "");
|
||||
boost::algorithm::replace_all(PatternString, "\\>", "");
|
||||
|
||||
int stringCompare = name.compare(PatternString);
|
||||
if (stringCompare == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool normalizePlayerName(std::string& name)
|
||||
{
|
||||
if (name.empty())
|
||||
@@ -8222,25 +8280,55 @@ bool isValidString(std::wstring wstr, uint32 strictMask, bool numericOrSpace, bo
|
||||
uint8 ObjectMgr::CheckPlayerName(std::string_view name, bool create)
|
||||
{
|
||||
std::wstring wname;
|
||||
|
||||
// Check for invalid characters
|
||||
if (!Utf8toWStr(name, wname))
|
||||
return CHAR_NAME_INVALID_CHARACTER;
|
||||
|
||||
// Check for too long name
|
||||
if (wname.size() > MAX_PLAYER_NAME)
|
||||
return CHAR_NAME_TOO_LONG;
|
||||
|
||||
// Check for too short name
|
||||
uint32 minName = sWorld->getIntConfig(CONFIG_MIN_PLAYER_NAME);
|
||||
if (wname.size() < minName)
|
||||
return CHAR_NAME_TOO_SHORT;
|
||||
|
||||
// Check for mixed languages
|
||||
uint32 strictMask = sWorld->getIntConfig(CONFIG_STRICT_PLAYER_NAMES);
|
||||
if (!isValidString(wname, strictMask, false, create))
|
||||
return CHAR_NAME_MIXED_LANGUAGES;
|
||||
|
||||
// Check for three consecutive letters
|
||||
wstrToLower(wname);
|
||||
for (size_t i = 2; i < wname.size(); ++i)
|
||||
if (wname[i] == wname[i - 1] && wname[i] == wname[i - 2])
|
||||
return CHAR_NAME_THREE_CONSECUTIVE;
|
||||
|
||||
// Check Reserved Name from Database
|
||||
if (sObjectMgr->IsReservedName(name))
|
||||
{
|
||||
return CHAR_NAME_RESERVED;
|
||||
}
|
||||
|
||||
// Check for Reserved Name from DBC
|
||||
if (sWorld->getBoolConfig(CONFIG_STRICT_NAMES_RESERVED))
|
||||
{
|
||||
if (ReservedNames(wname))
|
||||
{
|
||||
return CHAR_NAME_RESERVED;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for Profanity
|
||||
if (sWorld->getBoolConfig(CONFIG_STRICT_NAMES_PROFANITY))
|
||||
{
|
||||
if (ProfanityNames(wname))
|
||||
{
|
||||
return CHAR_NAME_PROFANE;
|
||||
}
|
||||
}
|
||||
|
||||
return CHAR_NAME_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -8257,6 +8345,24 @@ bool ObjectMgr::IsValidCharterName(std::string_view name)
|
||||
if (wname.size() < minName)
|
||||
return false;
|
||||
|
||||
// Check for Reserved Name from DBC
|
||||
if (sWorld->getBoolConfig(CONFIG_STRICT_NAMES_RESERVED))
|
||||
{
|
||||
if (ReservedNames(wname))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for Profanity
|
||||
if (sWorld->getBoolConfig(CONFIG_STRICT_NAMES_PROFANITY))
|
||||
{
|
||||
if (ProfanityNames(wname))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint32 strictMask = sWorld->getIntConfig(CONFIG_STRICT_CHARTER_NAMES);
|
||||
|
||||
return isValidString(wname, strictMask, true);
|
||||
@@ -8293,6 +8399,24 @@ PetNameInvalidReason ObjectMgr::CheckPetName(std::string_view name)
|
||||
if (!isValidString(wname, strictMask, false))
|
||||
return PET_NAME_MIXED_LANGUAGES;
|
||||
|
||||
// Check for Reserved Name from DBC
|
||||
if (sWorld->getBoolConfig(CONFIG_STRICT_NAMES_RESERVED))
|
||||
{
|
||||
if (ReservedNames(wname))
|
||||
{
|
||||
return PET_NAME_RESERVED;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for Profanity
|
||||
if (sWorld->getBoolConfig(CONFIG_STRICT_NAMES_PROFANITY))
|
||||
{
|
||||
if (ProfanityNames(wname))
|
||||
{
|
||||
return PET_NAME_PROFANE;
|
||||
}
|
||||
}
|
||||
|
||||
return PET_NAME_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -691,6 +691,8 @@ SkillRangeType GetSkillRangeType(SkillRaceClassInfoEntry const* rcEntry);
|
||||
#define MAX_CHARTER_NAME 24 // max allowed by client name length
|
||||
#define MAX_CHANNEL_NAME 50 // pussywizard
|
||||
|
||||
bool ReservedNames(std::wstring& name);
|
||||
bool ProfanityNames(std::wstring& name);
|
||||
bool normalizePlayerName(std::string& name);
|
||||
|
||||
struct LanguageDesc
|
||||
|
||||
@@ -356,12 +356,6 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData)
|
||||
return;
|
||||
}
|
||||
|
||||
if (AccountMgr::IsPlayerAccount(GetSecurity()) && sObjectMgr->IsReservedName(createInfo->Name))
|
||||
{
|
||||
SendCharCreate(CHAR_NAME_RESERVED);
|
||||
return;
|
||||
}
|
||||
|
||||
// speedup check for heroic class disabled case
|
||||
uint32 heroic_free_slots = sWorld->getIntConfig(CONFIG_HEROIC_CHARACTERS_PER_REALM);
|
||||
if (heroic_free_slots == 0 && AccountMgr::IsPlayerAccount(GetSecurity()) && createInfo->Class == CLASS_DEATH_KNIGHT)
|
||||
@@ -1351,13 +1345,6 @@ void WorldSession::HandleCharRenameOpcode(WorldPacket& recvData)
|
||||
return;
|
||||
}
|
||||
|
||||
// check name limitations
|
||||
if (AccountMgr::IsPlayerAccount(GetSecurity()) && sObjectMgr->IsReservedName(renameInfo->Name))
|
||||
{
|
||||
SendCharRename(CHAR_NAME_RESERVED, renameInfo.get());
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure that the character belongs to the current account, that rename at login is enabled
|
||||
// and that there is no character with the desired new name
|
||||
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_FREE_NAME);
|
||||
@@ -1698,13 +1685,6 @@ void WorldSession::HandleCharCustomizeCallback(std::shared_ptr<CharacterCustomiz
|
||||
return;
|
||||
}
|
||||
|
||||
// check name limitations
|
||||
if (AccountMgr::IsPlayerAccount(GetSecurity()) && sObjectMgr->IsReservedName(customizeInfo->Name))
|
||||
{
|
||||
SendCharCustomize(CHAR_NAME_RESERVED, customizeInfo.get());
|
||||
return;
|
||||
}
|
||||
|
||||
// character with this name already exist
|
||||
if (ObjectGuid newguid = sCharacterCache->GetCharacterGuidByName(customizeInfo->Name))
|
||||
{
|
||||
@@ -2083,13 +2063,6 @@ void WorldSession::HandleCharFactionOrRaceChangeCallback(std::shared_ptr<Charact
|
||||
return;
|
||||
}
|
||||
|
||||
// check name limitations
|
||||
if (AccountMgr::IsPlayerAccount(GetSecurity()) && sObjectMgr->IsReservedName(factionChangeInfo->Name))
|
||||
{
|
||||
SendCharFactionChange(CHAR_NAME_RESERVED, factionChangeInfo.get());
|
||||
return;
|
||||
}
|
||||
|
||||
// character with this name already exist
|
||||
if (ObjectGuid newguid = sCharacterCache->GetCharacterGuidByName(factionChangeInfo->Name))
|
||||
{
|
||||
|
||||
@@ -179,6 +179,8 @@ enum WorldBoolConfigs
|
||||
CONFIG_OBJECT_SPARKLES,
|
||||
CONFIG_LOW_LEVEL_REGEN_BOOST,
|
||||
CONFIG_OBJECT_QUEST_MARKERS,
|
||||
CONFIG_STRICT_NAMES_RESERVED,
|
||||
CONFIG_STRICT_NAMES_PROFANITY,
|
||||
CONFIG_ALLOWS_RANK_MOD_FOR_PET_HEALTH,
|
||||
BOOL_CONFIG_VALUE_COUNT
|
||||
};
|
||||
|
||||
@@ -718,6 +718,8 @@ void World::LoadConfigSettings(bool reload)
|
||||
else
|
||||
_int_configs[CONFIG_REALM_ZONE] = sConfigMgr->GetOption<int32>("RealmZone", REALM_ZONE_DEVELOPMENT);
|
||||
|
||||
_bool_configs[CONFIG_STRICT_NAMES_RESERVED] = sConfigMgr->GetOption<bool> ("StrictNames.Reserved", true);
|
||||
_bool_configs[CONFIG_STRICT_NAMES_PROFANITY] = sConfigMgr->GetOption<bool> ("StrictNames.Profanity", true);
|
||||
_int_configs[CONFIG_STRICT_PLAYER_NAMES] = sConfigMgr->GetOption<int32> ("StrictPlayerNames", 0);
|
||||
_int_configs[CONFIG_STRICT_CHARTER_NAMES] = sConfigMgr->GetOption<int32> ("StrictCharterNames", 0);
|
||||
_int_configs[CONFIG_STRICT_CHANNEL_NAMES] = sConfigMgr->GetOption<int32> ("StrictChannelNames", 0);
|
||||
|
||||
@@ -1377,6 +1377,20 @@ struct MovieEntry
|
||||
//uint32 unk2; // 2 always 100
|
||||
};
|
||||
|
||||
struct NamesReservedEntry
|
||||
{
|
||||
//uint32 ID; // 0
|
||||
char const* Pattern; // 1
|
||||
//uint32 Language; // 2
|
||||
};
|
||||
|
||||
struct NamesProfanityEntry
|
||||
{
|
||||
//uint32 ID; // 0
|
||||
char const* Pattern; // 1
|
||||
//uint32 Language; // 2
|
||||
};
|
||||
|
||||
#define MAX_OVERRIDE_SPELL 10
|
||||
|
||||
struct OverrideSpellDataEntry
|
||||
|
||||
@@ -84,6 +84,8 @@ char constexpr MailTemplateEntryfmt[] = "nxxxxxxxxxxxxxxxxxssssssssssssssssx";
|
||||
char constexpr MapEntryfmt[] = "nxiixssssssssssssssssxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixiffxiii";
|
||||
char constexpr MapDifficultyEntryfmt[] = "diisxxxxxxxxxxxxxxxxiix";
|
||||
char constexpr MovieEntryfmt[] = "nxx";
|
||||
char constexpr NamesReservedfmt[] = "xsx";
|
||||
char constexpr NamesProfanityfmt[] = "xsx";
|
||||
char constexpr OverrideSpellDatafmt[] = "niiiiiiiiiix";
|
||||
char constexpr PowerDisplayfmt[] = "nixxxx";
|
||||
char constexpr QuestSortEntryfmt[] = "nxxxxxxxxxxxxxxxxx";
|
||||
|
||||
Reference in New Issue
Block a user