Skip to content

Instantly share code, notes, and snippets.

@asfo
Last active April 13, 2023 01:57
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save asfo/851e2647b8e776dd14c84cd3293776de to your computer and use it in GitHub Desktop.
Save asfo/851e2647b8e776dd14c84cd3293776de to your computer and use it in GitHub Desktop.
Fake players for AzerothCore

How to use it:

Warning:It works only for AzerothCore and doesn't works on the last commit since it have some issues and the worldserver crashes, so that's why I'm not updating it to the latest version of AC, once that bug got fixed, I will update it.

  • Go to the root directory where you clone the repo, create a "patches" directory.
  • Create a file called fake_players.patch
  • Add the code above
  • Go back to the root directory
  • Run the command:
    git apply patches/fake_players.patch
    
  • Wait for it...(compile I mean)
  • Add the database:
DROP TABLE IF EXISTS `characters_fake`;
CREATE TABLE `characters_fake`  (
  `name` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `race` mediumint(3) NOT NULL DEFAULT 0,
  `class` mediumint(3) NOT NULL DEFAULT 0,
  `level` mediumint(3) NOT NULL DEFAULT 0,
  `zone` mediumint(9) NOT NULL DEFAULT 0,
  `gender` mediumint(3) NOT NULL DEFAULT 0,
  `online` smallint(1) NULL DEFAULT 1,
  UNIQUE INDEX `name`(`name`) USING BTREE,
  INDEX `level`(`level`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
  • Add some fake characters
  • Add a new string with the entry 12001 and the content_default as some message like "Do not disturb" or something in acore_strings in World database.
  • Set the configs

That's it. Credits for @conan-513 for the base

diff --git a/src/common/Database/Implementation/CharacterDatabase.cpp b/src/common/Database/Implementation/CharacterDatabase.cpp
index 09a664a5..c9e6d908 100644
--- a/src/common/Database/Implementation/CharacterDatabase.cpp
+++ b/src/common/Database/Implementation/CharacterDatabase.cpp
@@ -17,6 +17,12 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_DEL_EXPIRED_BANS, "UPDATE character_banned SET active = 0 WHERE unbandate <= UNIX_TIMESTAMP() AND unbandate <> bandate", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_DATA_BY_NAME, "SELECT guid, account, name, gender, race, class, level FROM characters WHERE deleteDate IS NULL AND name = ?", CONNECTION_BOTH);
PrepareStatement(CHAR_SEL_DATA_BY_GUID, "SELECT guid, account, name, gender, race, class, level FROM characters WHERE deleteDate IS NULL AND guid = ?", CONNECTION_BOTH);
+
+ PrepareStatement(FAKE_CHAR_SEL_RACE_BY_NAME, "SELECT race FROM characters_fake WHERE name = ?", CONNECTION_SYNCH);
+ PrepareStatement(FAKE_CHAR_SEL_RACE_BY_NAME_IS_ONLINE, "SELECT race FROM characters_fake WHERE online = 1 AND name = ?", CONNECTION_SYNCH);
+ PrepareStatement(FAKE_CHAR_ONLINE, "SELECT name,race,class,level,zone,gender FROM characters_fake WHERE online = 1", CONNECTION_SYNCH);
+ PrepareStatement(FAKE_CHAR_ONLINE_SEARCH, "SELECT name,race,class,level,zone,gender FROM characters_fake WHERE online = 1 AND name = ?", CONNECTION_SYNCH);
+
PrepareStatement(CHAR_SEL_CHECK_NAME, "SELECT 1 FROM characters WHERE name = ?", CONNECTION_BOTH);
PrepareStatement(CHAR_SEL_CHECK_GUID, "SELECT 1 FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_SUM_CHARS, "SELECT COUNT(guid) FROM characters WHERE account = ?", CONNECTION_BOTH);
diff --git a/src/common/Database/Implementation/CharacterDatabase.h b/src/common/Database/Implementation/CharacterDatabase.h
index 46d1c372..a280177b 100644
--- a/src/common/Database/Implementation/CharacterDatabase.h
+++ b/src/common/Database/Implementation/CharacterDatabase.h
@@ -31,6 +31,12 @@ enum CharacterDatabaseStatements
name for a suiting suffix.
*/
+ // Fake players patch
+ FAKE_CHAR_SEL_RACE_BY_NAME,
+ FAKE_CHAR_SEL_RACE_BY_NAME_IS_ONLINE,
+ FAKE_CHAR_ONLINE,
+ FAKE_CHAR_ONLINE_SEARCH,
+
CHAR_DEL_QUEST_POOL_SAVE,
CHAR_INS_QUEST_POOL_SAVE,
CHAR_DEL_NONEXISTENT_GUILD_BANK_ITEM,
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 9149fff6..7a6c295b 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -1787,7 +1787,16 @@ void Player::Update(uint32 p_time)
KillPlayer();
if (m_nextSave <= SavingSystemMgr::GetSavingCurrentValue() && !GetSession()->isLogingOut())
+ {
SaveToDB(false, false);
+
+ // If Fake WHO List system on then change player position with every SavePlayer Interval (usually 15min)
+ if (sWorld->getBoolConfig(CONFIG_FAKE_WHO_LIST))
+ {
+ CharacterDatabase.PExecute("UPDATE characters_fake SET zone = (FLOOR(50 * RAND()) + 1) WHERE online = 1");
+ CharacterDatabase.PExecute("UPDATE characters_fake SET level = level+1 WHERE level < 80 AND online = 1");
+ }
+ }
else if (m_additionalSaveTimer && !GetSession()->isLogingOut()) // pussywizard:
{
if (m_additionalSaveTimer <= p_time)
diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp
index 0679e7ce..35247689 100644
--- a/src/server/game/Guilds/Guild.cpp
+++ b/src/server/game/Guilds/Guild.cpp
@@ -1495,7 +1495,32 @@ void Guild::HandleInviteMember(WorldSession* session, std::string const& name)
Player* pInvitee = ObjectAccessor::FindPlayerByName(name, false);
if (!pInvitee)
{
- SendCommandResult(session, GUILD_COMMAND_INVITE, ERR_GUILD_PLAYER_NOT_FOUND_S, name);
+ /**
+ * Fake players patch
+ */
+ if (sWorld->getBoolConfig(CONFIG_FAKE_WHO_LIST))
+ {
+ PreparedStatement* fake = CharacterDatabase.GetPreparedStatement(FAKE_CHAR_SEL_RACE_BY_NAME_IS_ONLINE);
+ fake->setString(0, name);
+ PreparedQueryResult fakeresult = CharacterDatabase.Query(fake);
+
+ if (fakeresult)
+ {
+ Field* fields = fakeresult->Fetch();
+ uint32 team = Player::TeamIdForRace(fields[0].GetUInt8());
+
+ if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && team != session->GetPlayer()->GetTeamId())
+ {
+ SendCommandResult(session, GUILD_COMMAND_INVITE, ERR_GUILD_NOT_ALLIED, name);
+ }
+ else
+ {
+ ChatHandler(session->GetPlayer()->GetSession()).PSendSysMessage(LANG_FAKE_NOT_DISTURB);
+ }
+
+ return;
+ }
+ }
return;
}
diff --git a/src/server/game/Handlers/ChatHandler.cpp b/src/server/game/Handlers/ChatHandler.cpp
index 96147c1f..c2377d25 100644
--- a/src/server/game/Handlers/ChatHandler.cpp
+++ b/src/server/game/Handlers/ChatHandler.cpp
@@ -374,7 +374,15 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket & recvData)
bool receiverIsPlayer = AccountMgr::IsPlayerAccount(receiver ? receiver->GetSession()->GetSecurity() : SEC_PLAYER);
if (!receiver || (senderIsPlayer && !receiverIsPlayer && !receiver->isAcceptWhispers() && !receiver->IsInWhisperWhiteList(sender->GetGUID())))
{
- SendPlayerNotFoundNotice(to);
+ // If Fake WHO List system on then show player DND
+ if (sWorld->getBoolConfig(CONFIG_FAKE_WHO_LIST))
+ {
+ ChatHandler(sender->GetSession()).PSendSysMessage(LANG_FAKE_NOT_DISTURB);
+ }
+ else
+ {
+ SendPlayerNotFoundNotice(to);
+ }
return;
}
diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp
index acc5bfeb..b64fef98 100644
--- a/src/server/game/Handlers/GroupHandler.cpp
+++ b/src/server/game/Handlers/GroupHandler.cpp
@@ -21,6 +21,9 @@
#include "SpellAuras.h"
#include "Vehicle.h"
+#include "Chat.h"
+#include "Language.h"
+
class Aura;
/* differeces from off:
@@ -69,7 +72,14 @@ void WorldSession::HandleGroupInviteOpcode(WorldPacket& recvData)
// no player or cheat self-invite
if (!player || player == GetPlayer())
{
- SendPartyResult(PARTY_OP_INVITE, membername, ERR_BAD_PLAYER_NAME_S);
+ if (sWorld->getBoolConfig(CONFIG_FAKE_WHO_LIST))
+ {
+ ChatHandler(_player->GetSession()).PSendSysMessage(LANG_FAKE_NOT_DISTURB);
+ }
+ else
+ {
+ SendPartyResult(PARTY_OP_INVITE, membername, ERR_BAD_PLAYER_NAME_S);
+ }
return;
}
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index 48e2ab46..ead4fb57 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -229,6 +229,9 @@ void WorldSession::HandleWhoOpcode(WorldPacket& recvData)
uint32 zoneids[10]; // 10 is client limit
std::string player_name, guild_name;
+ bool searchBool = false;
+ std::string searchName;
+
recvData >> level_min; // maximal player level, default 0
recvData >> level_max; // minimal player level, default 100 (MAX_LEVEL)
recvData >> player_name; // player name, case sensitive...
@@ -268,6 +271,9 @@ void WorldSession::HandleWhoOpcode(WorldPacket& recvData)
wstrToLower(str[i]);
+ searchBool = true;
+ searchName = temp.c_str();
+
sLog->outDebug(LOG_FILTER_NETWORKIO, "String %u: %s", i, temp.c_str());
}
@@ -404,7 +410,47 @@ void WorldSession::HandleWhoOpcode(WorldPacket& recvData)
++displaycount;
}
- data.put(0, displaycount); // insert right count, count displayed
+ /**
+ * Fake players patch
+ */
+ if (sWorld->getBoolConfig(CONFIG_FAKE_WHO_LIST) && displaycount < 49)
+ {
+ //const char fake_players_db = (searchBool ? FAKE_CHAR_ONLINE_SEARCH : FAKE_CHAR_ONLINE);
+ PreparedStatement* fake = CharacterDatabase.GetPreparedStatement(searchBool ? FAKE_CHAR_ONLINE_SEARCH : FAKE_CHAR_ONLINE);
+
+ if (searchBool)
+ fake->setString(0, searchName);
+
+ PreparedQueryResult fakeresult = CharacterDatabase.Query(fake);
+ if (fakeresult)
+ {
+ do
+ {
+ Field *fields = fakeresult->Fetch();
+
+ std::string pname = fields[0].GetString(); // player name
+ std::string gname; // guild name
+ uint32 lvl = fields[3].GetUInt32(); // player level
+ uint32 class_ = fields[2].GetUInt32(); // player class
+ uint32 race = fields[1].GetUInt32(); // player race
+ uint32 pzoneid = fields[4].GetUInt32(); // player zone id
+ uint8 gender = fields[5].GetUInt8(); // player gender
+
+ data << pname; // player name
+ data << gname; // guild name
+ data << uint32(lvl); // player level
+ data << uint32(class_); // player class
+ data << uint32(race); // player race
+ data << uint8(gender); // player gender
+ data << uint32(pzoneid); // player zone id
+
+ if ((++matchcount) == 49)
+ break;
+ } while (fakeresult->NextRow());
+ }
+ }
+
+ data.put(0, matchcount);
data.put(4, matchcount); // insert right count, count of matches
SendPacket(&data);
@@ -596,6 +642,29 @@ void WorldSession::HandleAddFriendOpcode(WorldPacket & recv_data)
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: %s asked to add friend : '%s'", GetPlayer()->GetName().c_str(), friendName.c_str());
#endif
+ /**
+ * Fake players patch
+ */
+ if (sWorld->getBoolConfig(CONFIG_FAKE_WHO_LIST))
+ {
+ PreparedStatement* fake = CharacterDatabase.GetPreparedStatement(FAKE_CHAR_SEL_RACE_BY_NAME);
+ fake->setString(0, friendName);
+ PreparedQueryResult fakeresult = CharacterDatabase.Query(fake);
+
+ if (fakeresult)
+ {
+ Field* fields = fakeresult->Fetch();
+ uint32 team = Player::TeamIdForRace(fields[0].GetUInt8());
+
+ if (GetPlayer()->GetTeamId() != team && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND) && AccountMgr::IsPlayerAccount(GetSecurity()))
+ sSocialMgr->SendFriendStatus(_player, FRIEND_ENEMY, false, false);
+ else
+ ChatHandler(_player->GetSession()).PSendSysMessage(LANG_FAKE_NOT_DISTURB);
+
+ return;
+ }
+ }
+
// xinef: Get Data From global storage
uint32 guidLow = sWorld->GetGlobalPlayerGUID(friendName);
if (!guidLow)
@@ -706,6 +775,23 @@ void WorldSession::HandleAddIgnoreOpcode(WorldPacket & recv_data)
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Sent (SMSG_FRIEND_STATUS)");
#endif
+
+
+ /**
+ * Fake players patch
+ */
+ if (sWorld->getBoolConfig(CONFIG_FAKE_WHO_LIST))
+ {
+ PreparedStatement* fake = CharacterDatabase.GetPreparedStatement(FAKE_CHAR_SEL_RACE_BY_NAME_IS_ONLINE);
+ fake->setString(0, ignoreName);
+ PreparedQueryResult fakeresult = CharacterDatabase.Query(fake);
+
+ if (fakeresult)
+ {
+ ChatHandler(_player->GetSession()).PSendSysMessage(LANG_FAKE_NOT_DISTURB);
+ return;
+ }
+ }
}
void WorldSession::HandleLoadActionsSwitchSpec(PreparedQueryResult result)
diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h
index 415d16b4..6522d0ce 100644
--- a/src/server/game/Miscellaneous/Language.h
+++ b/src/server/game/Miscellaneous/Language.h
@@ -1309,6 +1309,9 @@ enum AcoreStrings
LANG_MUTED_PLAYER = 30000, // Mute for player 2 hour
+ // Fake players patch
+ LANG_FAKE_NOT_DISTURB = 12001,
+
// Instant Flight
LANG_TOGGLE_INSTANT_FLIGHT = 30077,
LANG_INSTANT_FLIGHT_ON = 30078,
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 00e01f3c..8a54af3f 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -735,6 +735,9 @@ void World::LoadConfigSettings(bool reload)
m_int_configs[CONFIG_STRICT_CHANNEL_NAMES] = sConfigMgr->GetIntDefault ("StrictChannelNames", 0);
m_int_configs[CONFIG_STRICT_PET_NAMES] = sConfigMgr->GetIntDefault ("StrictPetNames", 0);
+ m_bool_configs[CONFIG_FAKE_WHO_LIST] = sConfigMgr->GetBoolDefault("Fake.WHO.List", false);
+ m_int_configs[CONFIG_FAKE_WHO_LEVELUP_INTERVAL] = sConfigMgr->GetIntDefault("Fake.WHO.LevelUp.Interval", 2);
+
m_bool_configs[CONFIG_ALLOW_TWO_SIDE_ACCOUNTS] = sConfigMgr->GetBoolDefault("AllowTwoSide.Accounts", true);
m_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_CALENDAR]= sConfigMgr->GetBoolDefault("AllowTwoSide.Interaction.Calendar", false);
m_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT] = sConfigMgr->GetBoolDefault("AllowTwoSide.Interaction.Chat", false);
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index fc48301e..30ab0b1a 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -173,6 +173,7 @@ enum WorldBoolConfigs
CONFIG_ITEMDELETE_METHOD,
CONFIG_ITEMDELETE_VENDOR,
CONFIG_SET_ALL_CREATURES_WITH_WAYPOINT_MOVEMENT_ACTIVE,
+ CONFIG_FAKE_WHO_LIST, // Fake players patch
BOOL_CONFIG_VALUE_COUNT
};
@@ -352,6 +353,7 @@ enum WorldIntConfigs
CONFIG_ICC_BUFF_ALLIANCE,
CONFIG_ITEMDELETE_QUALITY,
CONFIG_ITEMDELETE_ITEM_LEVEL,
+ CONFIG_FAKE_WHO_LEVELUP_INTERVAL, // Fake patch update
INT_CONFIG_VALUE_COUNT
};
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
index ded2d5d0..8e08ce0f 100644
--- a/src/server/worldserver/worldserver.conf.dist
+++ b/src/server/worldserver/worldserver.conf.dist
@@ -3420,4 +3420,18 @@ PacketSpoof.BanMode = 0
PacketSpoof.BanDuration = 86400
#
-###################################################################################################
+###################################################################################################
+
+###################################################################################################
+#
+# Fake.WHO.List
+# Add fake players to fill in WHO LIST (who is online list, "O" button) if there is less then
+# 49 real players online
+# Default: 0 (disabled)
+# 1 (enabled)
+
+Fake.WHO.List = 1
+Fake.WHO.LevelUp.Interval = 2
+
+#
+###################################################################################################
@lach3v
Copy link

lach3v commented Feb 23, 2021

Hey there,
It's been awhile since your last revision and I wonder if you are going to update this patch ever. I tried to use the code to patch the core manually. Some parts of the above core code have been moved to different files, like the part shown in MiscHandler.cpp is now in Socialhandler.cpp, and the one in World.h now seems to be in IWorld.h

I tried to follow these changes and added the patch snippets there, but unfortunately I'm getting an error when compiling.

I hope you come back to this project and take a look.

@asfo
Copy link
Author

asfo commented Feb 24, 2021

Hey there,
It's been awhile since your last revision and I wonder if you are going to update this patch ever. I tried to use the code to patch the core manually. Some parts of the above core code have been moved to different files, like the part shown in MiscHandler.cpp is now in Socialhandler.cpp, and the one in World.h now seems to be in IWorld.h

I tried to follow these changes and added the patch snippets there, but unfortunately I'm getting an error when compiling.

I hope you come back to this project and take a look.

Sadly I'm not going to update it anymore.

We closed the server so, I just lost the interest in this ...sorry.

@lach3v
Copy link

lach3v commented Feb 24, 2021

That's really unfortune. Anyways best of luck!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment