mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-15 23:20:36 +01:00
Script/Commands: Add ".pdump copy" command (#25455)
* Script/Commands: Add ".pdump copy" command Syntax: .pdump copy $playerNameOrGUID $account [$newname] [$newguid] Copy character with name/guid $playerNameOrGUID into character list of $account with $newname, with first free or $newguid guid. * Add missing return * Restore eof check * Fix sql * Use forward declaration header Co-authored-by: Shauren <shauren.trinity@gmail.com> * Remove buffer when reading a line * Rename sql files Co-authored-by: Shauren <shauren.trinity@gmail.com>
This commit is contained in:
@@ -1783,7 +1783,8 @@ INSERT INTO `rbac_permissions` VALUES
|
||||
(876,'Command: lookup item id'),
|
||||
(877,'Command: lookup quest id'),
|
||||
(878,'Command: debug questreset'),
|
||||
(879,'Command: debug poolstatus');
|
||||
(879,'Command: debug poolstatus'),
|
||||
(880,'Command: pdump copy');
|
||||
/*!40000 ALTER TABLE `rbac_permissions` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
@@ -1972,7 +1973,8 @@ INSERT INTO `updates` VALUES
|
||||
('2020_08_15_00_auth.sql','A49F4A776E1583B1FF63DFE99BC0E0DD97A74674','ARCHIVED','2020-08-15 00:00:00',0),
|
||||
('2020_08_22_00_auth.sql','060A87FCC8F836A96D9D55BEDC32CBAD05008B4C','ARCHIVED','2020-08-22 00:00:00',0),
|
||||
('2020_09_06_00_auth.sql','DC4B5D4C65EB138D5609F137799C3289B9CC2493','ARCHIVED','2020-09-06 00:00:00',0),
|
||||
('2020_09_15_00_auth.sql','0AA5BCA384A372DC789647F838657766D51D8CC7','ARCHIVED','2020-09-15 19:35:18',0);
|
||||
('2020_09_15_00_auth.sql','0AA5BCA384A372DC789647F838657766D51D8CC7','ARCHIVED','2020-09-15 19:35:18',0),
|
||||
('2020_09_17_00_auth.sql','BBC0A8B2BBED38A57A83999909EB066753A893C5','ARCHIVED','2020-09-17 00:00:00',0);
|
||||
/*!40000 ALTER TABLE `updates` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
|
||||
3
sql/updates/auth/3.3.5/2020_09_17_00_auth.sql
Normal file
3
sql/updates/auth/3.3.5/2020_09_17_00_auth.sql
Normal file
@@ -0,0 +1,3 @@
|
||||
--
|
||||
DELETE FROM `rbac_permissions` WHERE `id`= 880;
|
||||
INSERT INTO `rbac_permissions` (`id`,`name`) VALUES (880, 'Command: pdump copy');
|
||||
5
sql/updates/world/3.3.5/2020_09_17_00_world.sql
Normal file
5
sql/updates/world/3.3.5/2020_09_17_00_world.sql
Normal file
@@ -0,0 +1,5 @@
|
||||
--
|
||||
DELETE FROM `command` WHERE `name`='pdump copy';
|
||||
INSERT INTO `command` (`name`,`permission`,`help`) VALUES
|
||||
('pdump copy',880,'Syntax: .pdump copy $playerNameOrGUID $account [$newname] [$newguid]
|
||||
Copy character with name/guid $playerNameOrGUID into character list of $account with $newname, with first free or $newguid guid.');
|
||||
@@ -781,6 +781,7 @@ enum RBACPermissions
|
||||
RBAC_PERM_COMMAND_LOOKUP_QUEST_ID = 877,
|
||||
RBAC_PERM_COMMAND_DEBUG_QUESTRESET = 878,
|
||||
RBAC_PERM_COMMAND_DEBUG_POOLSTATUS = 879,
|
||||
RBAC_PERM_COMMAND_PDUMP_COPY = 880,
|
||||
//
|
||||
// IF YOU ADD NEW PERMISSIONS, ADD THEM IN MASTER BRANCH AS WELL!
|
||||
//
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include "ObjectMgr.h"
|
||||
#include "Player.h"
|
||||
#include "World.h"
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
// static data
|
||||
enum GuidType : uint8
|
||||
@@ -712,7 +714,7 @@ bool PlayerDumpWriter::GetDump(ObjectGuid::LowType guid, std::string& dump)
|
||||
return true;
|
||||
}
|
||||
|
||||
DumpReturn PlayerDumpWriter::WriteDump(std::string const& file, ObjectGuid::LowType guid)
|
||||
DumpReturn PlayerDumpWriter::WriteDumpToFile(std::string const& file, ObjectGuid::LowType guid)
|
||||
{
|
||||
if (sWorld->getBoolConfig(CONFIG_PDUMP_NO_PATHS))
|
||||
if (strchr(file.c_str(), '\\') || strchr(file.c_str(), '/'))
|
||||
@@ -738,6 +740,14 @@ DumpReturn PlayerDumpWriter::WriteDump(std::string const& file, ObjectGuid::LowT
|
||||
return ret;
|
||||
}
|
||||
|
||||
DumpReturn PlayerDumpWriter::WriteDumpToString(std::string& dump, ObjectGuid::LowType guid)
|
||||
{
|
||||
DumpReturn ret = DUMP_SUCCESS;
|
||||
if (!GetDump(guid, dump))
|
||||
ret = DUMP_CHARACTER_DELETED;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Reading - High-level functions
|
||||
inline void FixNULLfields(std::string& line)
|
||||
{
|
||||
@@ -750,16 +760,12 @@ inline void FixNULLfields(std::string& line)
|
||||
}
|
||||
}
|
||||
|
||||
DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, std::string name, ObjectGuid::LowType guid)
|
||||
DumpReturn PlayerDumpReader::LoadDump(std::istream& input, uint32 account, std::string name, ObjectGuid::LowType guid)
|
||||
{
|
||||
uint32 charcount = AccountMgr::GetCharactersCount(account);
|
||||
if (charcount >= 10)
|
||||
return DUMP_TOO_MANY_CHARS;
|
||||
|
||||
FileHandle fin = GetFileHandle(file.c_str(), "r");
|
||||
if (!fin)
|
||||
return DUMP_FILE_OPEN_ERROR;
|
||||
|
||||
std::string newguid, chraccount;
|
||||
|
||||
// make sure the same guid doesn't already exist and is safe to use
|
||||
@@ -808,8 +814,7 @@ DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, s
|
||||
std::map<uint64, uint64> equipmentSetIds;
|
||||
uint64 equipmentSetGuidOffset = sObjectMgr->_equipmentSetGuid;
|
||||
|
||||
static size_t const BUFFER_SIZE = 32000;
|
||||
char buf[BUFFER_SIZE] = { };
|
||||
std::string line;
|
||||
|
||||
uint8 gender = GENDER_NONE;
|
||||
uint8 race = RACE_NONE;
|
||||
@@ -820,17 +825,8 @@ DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, s
|
||||
size_t lineNumber = 0;
|
||||
|
||||
CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
|
||||
while (!feof(fin.get()))
|
||||
while (std::getline(input, line))
|
||||
{
|
||||
if (!fgets(buf, BUFFER_SIZE, fin.get()))
|
||||
{
|
||||
if (feof(fin.get()))
|
||||
break;
|
||||
return DUMP_FILE_BROKEN;
|
||||
}
|
||||
|
||||
std::string line;
|
||||
line.assign(buf);
|
||||
++lineNumber;
|
||||
|
||||
// skip empty strings
|
||||
@@ -950,6 +946,9 @@ DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, s
|
||||
trans->Append(line.c_str());
|
||||
}
|
||||
|
||||
if (input.fail() && !input.eof())
|
||||
return DUMP_FILE_BROKEN;
|
||||
|
||||
CharacterDatabase.CommitTransaction(trans);
|
||||
|
||||
// in case of name conflict player has to rename at login anyway
|
||||
@@ -967,3 +966,17 @@ DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, s
|
||||
|
||||
return DUMP_SUCCESS;
|
||||
}
|
||||
|
||||
DumpReturn PlayerDumpReader::LoadDumpFromString(std::string const& dump, uint32 account, std::string name, ObjectGuid::LowType guid)
|
||||
{
|
||||
std::istringstream input(dump);
|
||||
return LoadDump(input, account, name, guid);
|
||||
}
|
||||
|
||||
DumpReturn PlayerDumpReader::LoadDumpFromFile(std::string const& file, uint32 account, std::string name, ObjectGuid::LowType guid)
|
||||
{
|
||||
std::ifstream input(file);
|
||||
if (!input)
|
||||
return DUMP_FILE_OPEN_ERROR;
|
||||
return LoadDump(input, account, name, guid);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#define _PLAYER_DUMP_H
|
||||
|
||||
#include <string>
|
||||
#include <iosfwd>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include "ObjectGuid.h"
|
||||
@@ -79,7 +80,8 @@ class TC_GAME_API PlayerDumpWriter : public PlayerDump
|
||||
PlayerDumpWriter() { }
|
||||
|
||||
bool GetDump(ObjectGuid::LowType guid, std::string& dump);
|
||||
DumpReturn WriteDump(std::string const& file, ObjectGuid::LowType guid);
|
||||
DumpReturn WriteDumpToFile(std::string const& file, ObjectGuid::LowType guid);
|
||||
DumpReturn WriteDumpToString(std::string& dump, ObjectGuid::LowType guid);
|
||||
|
||||
private:
|
||||
bool AppendTable(StringTransaction& trans, ObjectGuid::LowType guid, TableStruct const& tableStruct, DumpTable const& dumpTable);
|
||||
@@ -97,7 +99,11 @@ class TC_GAME_API PlayerDumpReader : public PlayerDump
|
||||
public:
|
||||
PlayerDumpReader() { }
|
||||
|
||||
DumpReturn LoadDump(std::string const& file, uint32 account, std::string name, ObjectGuid::LowType guid);
|
||||
DumpReturn LoadDumpFromFile(std::string const& file, uint32 account, std::string name, ObjectGuid::LowType guid);
|
||||
DumpReturn LoadDumpFromString(std::string const& dump, uint32 account, std::string name, ObjectGuid::LowType guid);
|
||||
|
||||
private:
|
||||
DumpReturn LoadDump(std::istream& input, uint32 account, std::string name, ObjectGuid::LowType guid);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -47,6 +47,7 @@ public:
|
||||
{
|
||||
static std::vector<ChatCommand> pdumpCommandTable =
|
||||
{
|
||||
{ "copy", rbac::RBAC_PERM_COMMAND_PDUMP_COPY, true, &HandlePDumpCopyCommand, "" },
|
||||
{ "load", rbac::RBAC_PERM_COMMAND_PDUMP_LOAD, true, &HandlePDumpLoadCommand, "" },
|
||||
{ "write", rbac::RBAC_PERM_COMMAND_PDUMP_WRITE, true, &HandlePDumpWriteCommand, "" },
|
||||
};
|
||||
@@ -779,9 +780,84 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool HandlePDumpCopyCommand(ChatHandler* handler, PlayerIdentifier player, AccountIdentifier account, Optional<std::string_view> characterName, Optional<ObjectGuid::LowType> characterGUID)
|
||||
{
|
||||
std::string name;
|
||||
if (!ValidatePDumpTarget(handler, name, characterName, characterGUID))
|
||||
return false;
|
||||
|
||||
std::string dump;
|
||||
switch (PlayerDumpWriter().WriteDumpToString(dump, player.GetGUID().GetCounter()))
|
||||
{
|
||||
case DUMP_SUCCESS:
|
||||
break;
|
||||
case DUMP_CHARACTER_DELETED:
|
||||
handler->PSendSysMessage(LANG_COMMAND_EXPORT_DELETED_CHAR);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
case DUMP_FILE_OPEN_ERROR: // this error code should not happen
|
||||
default:
|
||||
handler->PSendSysMessage(LANG_COMMAND_EXPORT_FAILED);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (PlayerDumpReader().LoadDumpFromString(dump, account, name, characterGUID.value_or(0)))
|
||||
{
|
||||
case DUMP_SUCCESS:
|
||||
break;
|
||||
case DUMP_TOO_MANY_CHARS:
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_CHARACTER_LIST_FULL, account.GetName().c_str(), account.GetID());
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
case DUMP_FILE_OPEN_ERROR: // this error code should not happen
|
||||
case DUMP_FILE_BROKEN: // this error code should not happen
|
||||
default:
|
||||
handler->PSendSysMessage(LANG_COMMAND_IMPORT_FAILED);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
// ToDo: use a new trinity_string for this commands
|
||||
handler->PSendSysMessage(LANG_COMMAND_IMPORT_SUCCESS);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool HandlePDumpLoadCommand(ChatHandler* handler, std::string fileName, AccountIdentifier account, Optional<std::string_view> characterName, Optional<ObjectGuid::LowType> characterGUID)
|
||||
{
|
||||
std::string name;
|
||||
if (!ValidatePDumpTarget(handler, name, characterName, characterGUID))
|
||||
return false;
|
||||
|
||||
switch (PlayerDumpReader().LoadDumpFromFile(fileName, account, name, characterGUID.value_or(0)))
|
||||
{
|
||||
case DUMP_SUCCESS:
|
||||
handler->PSendSysMessage(LANG_COMMAND_IMPORT_SUCCESS);
|
||||
break;
|
||||
case DUMP_FILE_OPEN_ERROR:
|
||||
handler->PSendSysMessage(LANG_FILE_OPEN_FAIL, fileName.c_str());
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
case DUMP_FILE_BROKEN:
|
||||
handler->PSendSysMessage(LANG_DUMP_BROKEN, fileName.c_str());
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
case DUMP_TOO_MANY_CHARS:
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_CHARACTER_LIST_FULL, account.GetName().c_str(), account.GetID());
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
default:
|
||||
handler->PSendSysMessage(LANG_COMMAND_IMPORT_FAILED);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ValidatePDumpTarget(ChatHandler* handler, std::string& name, Optional<std::string_view> characterName, Optional<ObjectGuid::LowType> characterGUID)
|
||||
{
|
||||
if (characterName)
|
||||
{
|
||||
name.assign(*characterName);
|
||||
@@ -811,35 +887,12 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
switch (PlayerDumpReader().LoadDump(fileName, account, name, characterGUID.value_or(0)))
|
||||
{
|
||||
case DUMP_SUCCESS:
|
||||
handler->PSendSysMessage(LANG_COMMAND_IMPORT_SUCCESS);
|
||||
break;
|
||||
case DUMP_FILE_OPEN_ERROR:
|
||||
handler->PSendSysMessage(LANG_FILE_OPEN_FAIL, fileName.c_str());
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
case DUMP_FILE_BROKEN:
|
||||
handler->PSendSysMessage(LANG_DUMP_BROKEN, fileName.c_str());
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
case DUMP_TOO_MANY_CHARS:
|
||||
handler->PSendSysMessage(LANG_ACCOUNT_CHARACTER_LIST_FULL, account.GetName().c_str(), account.GetID());
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
default:
|
||||
handler->PSendSysMessage(LANG_COMMAND_IMPORT_FAILED);
|
||||
handler->SetSentErrorMessage(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool HandlePDumpWriteCommand(ChatHandler* handler, std::string fileName, PlayerIdentifier player)
|
||||
{
|
||||
switch (PlayerDumpWriter().WriteDump(fileName, player.GetGUID().GetCounter()))
|
||||
switch (PlayerDumpWriter().WriteDumpToFile(fileName, player.GetGUID().GetCounter()))
|
||||
{
|
||||
case DUMP_SUCCESS:
|
||||
handler->PSendSysMessage(LANG_COMMAND_EXPORT_SUCCESS);
|
||||
|
||||
Reference in New Issue
Block a user