diff options
| author | fusion32 <marcopuzziello@gmail.com> | 2025-07-02 13:28:45 -0300 |
|---|---|---|
| committer | fusion32 <marcopuzziello@gmail.com> | 2025-07-02 13:28:45 -0300 |
| commit | e782274ade8d7307e157a997d6ac3bcaa4130024 (patch) | |
| tree | 7999cc2737817db3e4c22bf94236ade6d5dd0d95 /src | |
| parent | aaf198773fd8e041b0976cc0682e83f8acf394d0 (diff) | |
| download | game-e782274ade8d7307e157a997d6ac3bcaa4130024.tar.gz game-e782274ade8d7307e157a997d6ac3bcaa4130024.zip | |
`query.cc`
Diffstat (limited to 'src')
| -rw-r--r-- | src/communication.cc | 2 | ||||
| -rw-r--r-- | src/houses.cc | 20 | ||||
| -rw-r--r-- | src/map.hh | 4 | ||||
| -rw-r--r-- | src/query.cc | 1352 | ||||
| -rw-r--r-- | src/query.hh | 117 |
5 files changed, 1441 insertions, 54 deletions
diff --git a/src/communication.cc b/src/communication.cc index bb71327..9f0e6e5 100644 --- a/src/communication.cc +++ b/src/communication.cc @@ -427,7 +427,7 @@ bool SendData(TConnection *Connection, const uint8 *Data, int Size){ // Waiting List // ============================================================================= -bool GetWaitinglistEntry(const char *Name, int *NextTry, bool *FreeAccount, bool *Newbie){ +bool GetWaitinglistEntry(const char *Name, uint32 *NextTry, bool *FreeAccount, bool *Newbie){ bool Result = false; CommunicationThreadMutex.down(); TWaitinglistEntry *Entry = WaitinglistHead; diff --git a/src/houses.cc b/src/houses.cc index b47138e..4c06419 100644 --- a/src/houses.cc +++ b/src/houses.cc @@ -1670,16 +1670,16 @@ void LoadHouses(void){ Houses += 1; } - uint16 *HouseIDs = (uint16*)alloca(Houses * sizeof(uint16)); - char **Names = (char**)alloca(Houses * sizeof(char*)); - int *Rents = (int*)alloca(Houses * sizeof(int)); - char **Descriptions = (char**)alloca(Houses * sizeof(char*)); - int *Sizes = (int*)alloca(Houses * sizeof(int)); - int *PositionsX = (int*)alloca(Houses * sizeof(int)); - int *PositionsY = (int*)alloca(Houses * sizeof(int)); - int *PositionsZ = (int*)alloca(Houses * sizeof(int)); - char (*Towns)[30] = (char(*)[30])alloca(Houses * 30); - bool *Guildhouses = (bool*)alloca(Houses * sizeof(bool)); + uint16 *HouseIDs = (uint16*)alloca(Houses * sizeof(uint16)); + const char **Names = (const char**)alloca(Houses * sizeof(const char*)); + int *Rents = (int*)alloca(Houses * sizeof(int)); + const char **Descriptions = (const char**)alloca(Houses * sizeof(const char*)); + int *Sizes = (int*)alloca(Houses * sizeof(int)); + int *PositionsX = (int*)alloca(Houses * sizeof(int)); + int *PositionsY = (int*)alloca(Houses * sizeof(int)); + int *PositionsZ = (int*)alloca(Houses * sizeof(int)); + char (*Towns)[30] = (char(*)[30])alloca(Houses * 30); + bool *Guildhouses = (bool*)alloca(Houses * sizeof(bool)); for(int HouseNr = 0; HouseNr < Houses; HouseNr += 1){ THouse *H = House.at(HouseNr); HouseIDs[HouseNr] = H->ID; @@ -120,9 +120,9 @@ uint32 CronInfo(Object Obj, bool Delete); uint32 CronStop(Object Obj); // NOTE(fusion): Map management functions. Most for internal use. -void SwapObject(TWriteBinaryFile *File, Object Obj, uint32 FileNumber); +void SwapObject(TWriteBinaryFile *File, Object Obj, uintptr FileNumber); void SwapSector(void); -void UnswapSector(uint32 FileNumber); +void UnswapSector(uintptr FileNumber); void DeleteSwappedSectors(void); void LoadObjects(TReadScriptFile *Script, TWriteStream *Stream, bool Skip); void LoadObjects(TReadStream *Stream, Object Con); diff --git a/src/query.cc b/src/query.cc index a31b9b0..5da269d 100644 --- a/src/query.cc +++ b/src/query.cc @@ -20,6 +20,8 @@ void SetQueryManagerLoginData(int Type, const char *Data){ } } +// TQueryManagerConnection +// ============================================================================= // TODO(fusion): An initializer list executes in the same order fields are // declared. This initialization should work as long as `BufferSize` is the // first field declared in `TQueryManagerConnection`, which it is. @@ -373,6 +375,8 @@ int TQueryManagerConnection::executeQuery(int Timeout, bool AutoReconnect){ return QUERY_FAILED; } + this->ReadBuffer.Size = ResponseSize; + this->ReadBuffer.Position = 0; int Status = this->getByte(); if(Status == QUERY_FAILED){ error("TQueryManagerConnection::executeQuery: Anfrage fehlgeschlagen.\n"); @@ -381,3 +385,1351 @@ int TQueryManagerConnection::executeQuery(int Timeout, bool AutoReconnect){ return Status; } } + +int TQueryManagerConnection::checkAccountPassword(uint32 AccountID, + const char *Password, const char *IPAddress){ + this->prepareQuery(10); + this->sendQuad(AccountID); + this->sendString(Password); + this->sendString(IPAddress); + int Status = this->executeQuery(30, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_ERROR){ + int ErrorCode = this->getByte(); + if(ErrorCode >= 1 && ErrorCode <= 4){ + Result = ErrorCode; + }else{ + error("TQueryManagerConnection::checkAccountPassword: Ungültiger Fehlercode %d.\n", ErrorCode); + } + } + return Result; +} + +int TQueryManagerConnection::loginAdmin(uint32 AccountID, bool PrivateWorld, + int *NumberOfCharacters, char (*Characters)[30], char (*Worlds)[30], + uint8 (*IPAddresses)[4], uint16 *Ports, uint16 *PremiumDaysLeft){ + this->prepareQuery(12); + this->sendQuad(AccountID); + this->sendFlag(PrivateWorld); + int Status = this->executeQuery(30, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_OK){ + *NumberOfCharacters = this->getByte(); + for(int i = 0; i < *NumberOfCharacters; i += 1){ + this->getString(Characters[i], 30); + this->getString(Worlds[i], 30); + this->getBytes(IPAddresses[i], 4); + Ports[i] = this->getWord(); + } + *PremiumDaysLeft = this->getWord(); + }else if(Status == QUERY_ERROR){ + int ErrorCode = this->getByte(); + if(ErrorCode == 1){ + Result = ErrorCode; + }else{ + error("TQueryManagerConnection::loginAdmin: Ungültiger Fehlercode %d.\n", ErrorCode); + } + } + return Result; +} + +int TQueryManagerConnection::loadWorldConfig(int *WorldType, int *RebootTime, + int *IPAddress, int *Port, int *MaxPlayers, int *PremiumPlayerBuffer, + int *MaxNewbies, int *PremiumNewbieBuffer){ + this->prepareQuery(53); + int Status = this->executeQuery(30, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_OK){ + *WorldType = this->getByte(); + *RebootTime = (int)this->getByte() * 60; + IPAddress[0] = this->getByte(); + IPAddress[1] = this->getByte(); + IPAddress[2] = this->getByte(); + IPAddress[3] = this->getByte(); + *Port = this->getWord(); + *MaxPlayers = this->getWord(); + *PremiumPlayerBuffer = this->getWord(); + *MaxNewbies = this->getWord(); + *PremiumNewbieBuffer = this->getWord(); + } + return Result; +} + +static int GetRightByName(const char *RightName){ + int Result = -1; + if(strcmp(RightName, "PREMIUM_ACCOUNT") == 0){ + Result = PREMIUM_ACCOUNT; + }else if(strcmp(RightName, "NOTATION") == 0){ + Result = NOTATION; + }else if(strcmp(RightName, "NAMELOCK") == 0){ + Result = NAMELOCK; + }else if(strcmp(RightName, "STATEMENT_REPORT") == 0){ + Result = STATEMENT_REPORT; + }else if(strcmp(RightName, "BANISHMENT") == 0){ + Result = BANISHMENT; + }else if(strcmp(RightName, "FINAL_WARNING") == 0){ + Result = FINAL_WARNING; + }else if(strcmp(RightName, "IP_BANISHMENT") == 0){ + Result = IP_BANISHMENT; + }else if(strcmp(RightName, "KICK") == 0){ + Result = KICK; + }else if(strcmp(RightName, "HOME_TELEPORT") == 0){ + Result = HOME_TELEPORT; + }else if(strcmp(RightName, "GAMEMASTER_BROADCAST") == 0){ + Result = GAMEMASTER_BROADCAST; + }else if(strcmp(RightName, "ANONYMOUS_BROADCAST") == 0){ + Result = ANONYMOUS_BROADCAST; + }else if(strcmp(RightName, "NO_BANISHMENT") == 0){ + Result = NO_BANISHMENT; + }else if(strcmp(RightName, "ALLOW_MULTICLIENT") == 0){ + Result = ALLOW_MULTICLIENT; + }else if(strcmp(RightName, "LOG_COMMUNICATION") == 0){ + Result = LOG_COMMUNICATION; + }else if(strcmp(RightName, "READ_GAMEMASTER_CHANNEL") == 0){ + Result = READ_GAMEMASTER_CHANNEL; + }else if(strcmp(RightName, "READ_TUTOR_CHANNEL") == 0){ + Result = READ_TUTOR_CHANNEL; + }else if(strcmp(RightName, "HIGHLIGHT_HELP_CHANNEL") == 0){ + Result = HIGHLIGHT_HELP_CHANNEL; + }else if(strcmp(RightName, "SEND_BUGREPORTS") == 0){ + Result = SEND_BUGREPORTS; + }else if(strcmp(RightName, "NAME_INSULTING") == 0){ + Result = NAME_INSULTING; + }else if(strcmp(RightName, "NAME_SENTENCE") == 0){ + Result = NAME_SENTENCE; + }else if(strcmp(RightName, "NAME_NONSENSICAL_LETTERS") == 0){ + Result = NAME_NONSENSICAL_LETTERS; + }else if(strcmp(RightName, "NAME_BADLY_FORMATTED") == 0){ + Result = NAME_BADLY_FORMATTED; + }else if(strcmp(RightName, "NAME_NO_PERSON") == 0){ + Result = NAME_NO_PERSON; + }else if(strcmp(RightName, "NAME_CELEBRITY") == 0){ + Result = NAME_CELEBRITY; + }else if(strcmp(RightName, "NAME_COUNTRY") == 0){ + Result = NAME_COUNTRY; + }else if(strcmp(RightName, "NAME_FAKE_IDENTITY") == 0){ + Result = NAME_FAKE_IDENTITY; + }else if(strcmp(RightName, "NAME_FAKE_POSITION") == 0){ + Result = NAME_FAKE_POSITION; + }else if(strcmp(RightName, "STATEMENT_INSULTING") == 0){ + Result = STATEMENT_INSULTING; + }else if(strcmp(RightName, "STATEMENT_SPAMMING") == 0){ + Result = STATEMENT_SPAMMING; + }else if(strcmp(RightName, "STATEMENT_ADVERT_OFFTOPIC") == 0){ + Result = STATEMENT_ADVERT_OFFTOPIC; + }else if(strcmp(RightName, "STATEMENT_ADVERT_MONEY") == 0){ + Result = STATEMENT_ADVERT_MONEY; + }else if(strcmp(RightName, "STATEMENT_NON_ENGLISH") == 0){ + Result = STATEMENT_NON_ENGLISH; + }else if(strcmp(RightName, "STATEMENT_CHANNEL_OFFTOPIC") == 0){ + Result = STATEMENT_CHANNEL_OFFTOPIC; + }else if(strcmp(RightName, "STATEMENT_VIOLATION_INCITING") == 0){ + Result = STATEMENT_VIOLATION_INCITING; + }else if(strcmp(RightName, "CHEATING_BUG_ABUSE") == 0){ + Result = CHEATING_BUG_ABUSE; + }else if(strcmp(RightName, "CHEATING_GAME_WEAKNESS") == 0){ + Result = CHEATING_GAME_WEAKNESS; + }else if(strcmp(RightName, "CHEATING_MACRO_USE") == 0){ + Result = CHEATING_MACRO_USE; + }else if(strcmp(RightName, "CHEATING_MODIFIED_CLIENT") == 0){ + Result = CHEATING_MODIFIED_CLIENT; + }else if(strcmp(RightName, "CHEATING_HACKING") == 0){ + Result = CHEATING_HACKING; + }else if(strcmp(RightName, "CHEATING_MULTI_CLIENT") == 0){ + Result = CHEATING_MULTI_CLIENT; + }else if(strcmp(RightName, "CHEATING_ACCOUNT_TRADING") == 0){ + Result = CHEATING_ACCOUNT_TRADING; + }else if(strcmp(RightName, "CHEATING_ACCOUNT_SHARING") == 0){ + Result = CHEATING_ACCOUNT_SHARING; + }else if(strcmp(RightName, "GAMEMASTER_THREATENING") == 0){ + Result = GAMEMASTER_THREATENING; + }else if(strcmp(RightName, "GAMEMASTER_PRETENDING") == 0){ + Result = GAMEMASTER_PRETENDING; + }else if(strcmp(RightName, "GAMEMASTER_INFLUENCE") == 0){ + Result = GAMEMASTER_INFLUENCE; + }else if(strcmp(RightName, "GAMEMASTER_FALSE_REPORTS") == 0){ + Result = GAMEMASTER_FALSE_REPORTS; + }else if(strcmp(RightName, "KILLING_EXCESSIVE_UNJUSTIFIED") == 0){ + Result = KILLING_EXCESSIVE_UNJUSTIFIED; + }else if(strcmp(RightName, "DESTRUCTIVE_BEHAVIOUR") == 0){ + Result = DESTRUCTIVE_BEHAVIOUR; + }else if(strcmp(RightName, "SPOILING_AUCTION") == 0){ + Result = SPOILING_AUCTION; + }else if(strcmp(RightName, "INVALID_PAYMENT") == 0){ + Result = INVALID_PAYMENT; + }else if(strcmp(RightName, "TELEPORT_TO_CHARACTER") == 0){ + Result = TELEPORT_TO_CHARACTER; + }else if(strcmp(RightName, "TELEPORT_TO_MARK") == 0){ + Result = TELEPORT_TO_MARK; + }else if(strcmp(RightName, "TELEPORT_VERTICAL") == 0){ + Result = TELEPORT_VERTICAL; + }else if(strcmp(RightName, "TELEPORT_TO_COORDINATE") == 0){ + Result = TELEPORT_TO_COORDINATE; + }else if(strcmp(RightName, "LEVITATE") == 0){ + Result = LEVITATE; + }else if(strcmp(RightName, "SPECIAL_MOVEUSE") == 0){ + Result = SPECIAL_MOVEUSE; + }else if(strcmp(RightName, "MODIFY_GOSTRENGTH") == 0){ + Result = MODIFY_GOSTRENGTH; + }else if(strcmp(RightName, "SHOW_COORDINATE") == 0){ + Result = SHOW_COORDINATE; + }else if(strcmp(RightName, "RETRIEVE") == 0){ + Result = RETRIEVE; + }else if(strcmp(RightName, "ENTER_HOUSES") == 0){ + Result = ENTER_HOUSES; + }else if(strcmp(RightName, "OPEN_NAMEDOORS") == 0){ + // TODO(fusion): The actual name was "OPEN_NAMEDDOORS" but could be a typo? + // Either way, it doesn't make that much of a difference since there is no + // actual query manager outside the ones we might build ourselves. + Result = OPEN_NAMEDOORS; + }else if(strcmp(RightName, "INVULNERABLE") == 0){ + Result = INVULNERABLE; + }else if(strcmp(RightName, "UNLIMITED_MANA") == 0){ + Result = UNLIMITED_MANA; + }else if(strcmp(RightName, "KEEP_INVENTORY") == 0){ + Result = KEEP_INVENTORY; + }else if(strcmp(RightName, "ALL_SPELLS") == 0){ + Result = ALL_SPELLS; + }else if(strcmp(RightName, "UNLIMITED_CAPACITY") == 0){ + Result = UNLIMITED_CAPACITY; + }else if(strcmp(RightName, "ZERO_CAPACITY") == 0){ + Result = ZERO_CAPACITY; + }else if(strcmp(RightName, "ATTACK_EVERYWHERE") == 0){ + Result = ATTACK_EVERYWHERE; + }else if(strcmp(RightName, "NO_ATTACK") == 0){ + Result = NO_ATTACK; + }else if(strcmp(RightName, "NO_RUNES") == 0){ + Result = NO_RUNES; + }else if(strcmp(RightName, "NO_LOGOUT_BLOCK") == 0){ + Result = NO_LOGOUT_BLOCK; + }else if(strcmp(RightName, "GAMEMASTER_OUTFIT") == 0){ + Result = GAMEMASTER_OUTFIT; + }else if(strcmp(RightName, "ILLUMINATE") == 0){ + Result = ILLUMINATE; + }else if(strcmp(RightName, "CHANGE_PROFESSION") == 0){ + Result = CHANGE_PROFESSION; + }else if(strcmp(RightName, "IGNORED_BY_MONSTERS") == 0){ + Result = IGNORED_BY_MONSTERS; + }else if(strcmp(RightName, "SHOW_KEYHOLE_NUMBERS") == 0){ + Result = SHOW_KEYHOLE_NUMBERS; + }else if(strcmp(RightName, "CREATE_OBJECTS") == 0){ + Result = CREATE_OBJECTS; + }else if(strcmp(RightName, "CREATE_MONEY") == 0){ + Result = CREATE_MONEY; + }else if(strcmp(RightName, "CREATE_MONSTERS") == 0){ + Result = CREATE_MONSTERS; + }else if(strcmp(RightName, "CHANGE_SKILLS") == 0){ + Result = CHANGE_SKILLS; + }else if(strcmp(RightName, "CLEANUP_FIELDS") == 0){ + Result = CLEANUP_FIELDS; + }else if(strcmp(RightName, "NO_STATISTICS") == 0){ + Result = NO_STATISTICS; + } + return Result; +} + +// NOTE(fusion): These seem to be related to forums and an admin panel. +static bool IsAdministrativeRight(const char *RightName){ + return strcmp(RightName, "CLEAR_CHARACTER_INFO") == 0 + || strcmp(RightName, "CLEAR_GUILDS") == 0 + || strcmp(RightName, "DELETE_GUILDS") == 0 + || strcmp(RightName, "BOARD_REPORT") == 0 + || strcmp(RightName, "BOARD_MODERATION") == 0 + || strcmp(RightName, "BOARD_ANONYMOUS_EDIT") == 0 + || strcmp(RightName, "BOARD_PRECONFIRMED") == 0 + || strcmp(RightName, "KEEP_ACCOUNT") == 0 + || strcmp(RightName, "INVITED") == 0 + || strcmp(RightName, "CIPWATCH_ADMIN") == 0 + || strcmp(RightName, "CIPWATCH_USER") == 0 + || strcmp(RightName, "CREATECHAR_GAMEMASTER") == 0 + || strcmp(RightName, "CREATECHAR_GOD") == 0 + || strcmp(RightName, "CREATECHAR_TEST") == 0 + || strcmp(RightName, "VIEW_ACCOUNT") == 0 + || strcmp(RightName, "VIEW_GAMEMASTER_RECORD") == 0 + || strcmp(RightName, "VIEW_CRIMINAL_RECORD") == 0 + || strcmp(RightName, "VIEW_LOG_FILES") == 0 + || strcmp(RightName, "MODIFY_BANISHMENT") == 0 + || strcmp(RightName, "APPOINT_CIP") == 0 + || strcmp(RightName, "APPOINT_SGM") == 0 + || strcmp(RightName, "APPOINT_JGM") == 0 + || strcmp(RightName, "APPOINT_SENATOR") == 0 + || strcmp(RightName, "SET_ACCOUNT_RIGHTS") == 0 + || strcmp(RightName, "SET_CHARACTER_RIGHTS") == 0 + || strcmp(RightName, "SET_ACCOUNTGROUP_RIGHTS") == 0 + || strcmp(RightName, "SET_CHARACTERGROUP_RIGHTS") == 0 + || strcmp(RightName, "KEEP_CHARACTER") == 0 + || strcmp(RightName, "EXTRA_CHARACTER") == 0; +} + +// NOTE(fusion): `PlayerName` is an input and output parameter. It will contain +// the correct player name with upper and lower case letters if the operation is +// successful. +int TQueryManagerConnection::loginGame(uint32 AccountID, char *PlayerName, + const char *Password, const char *IPAddress, bool PrivateWorld, + bool PremiumAccountRequired, bool GamemasterRequired, uint32 *CharacterID, + int *Sex, char *Guild, char *Rank, char *Title, int *NumberOfBuddies, + uint32 *BuddyIDs, char (*BuddyNames)[30], uint8 *Rights, + bool *PremiumAccountActivated){ + this->prepareQuery(20); + this->sendQuad(AccountID); + this->sendString(PlayerName); + this->sendString(Password); + this->sendString(IPAddress); + this->sendFlag(PrivateWorld); + this->sendFlag(PremiumAccountRequired); + this->sendFlag(GamemasterRequired); + int Status = this->executeQuery(120, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_OK){ + *CharacterID = this->getQuad(); + this->getString(PlayerName, 30); + *Sex = this->getByte(); + this->getString(Guild, 30); + this->getString(Rank, 30); + this->getString(Title, 30); + *NumberOfBuddies = this->getByte(); + + int SkipBuddies = 0; + if(*NumberOfBuddies > 100){ // MAX_BUDDIES + error("TQueryManagerConnection::loginGame: zu viele Buddys (%d) für %s.\n", + *NumberOfBuddies, PlayerName); + SkipBuddies = *NumberOfBuddies - 100; + *NumberOfBuddies = 100; + } + + for(int i = 0; i < *NumberOfBuddies; i += 1){ + BuddyIDs[i] = this->getQuad(); + this->getString(BuddyNames[i], 30); + } + + if(SkipBuddies > 0){ + char BuddyName[30]; + for(int i = 0; i < SkipBuddies; i += 1){ + this->getQuad(); + this->getString(BuddyName, 30); + } + } + + int NumberOfRights = this->getByte(); + for(int i = 0; i < NumberOfRights; i += 1){ + char RightName[30]; + this->getString(RightName, 30); + int Right = GetRightByName(RightName); + if(Right != -1){ + SetBit(Rights, Right); + }else if(!IsAdministrativeRight(RightName)){ + error("TQueryManagerConnection::loginGame: Unbekanntes Recht %s.\n", RightName); + } + } + + *PremiumAccountActivated = this->getFlag(); + }else if(Status == QUERY_ERROR){ + int ErrorCode = this->getByte(); + if(ErrorCode >= 1 && ErrorCode <= 15){ + Result = ErrorCode; + }else{ + error("TQueryManagerConnection::loginGame: Ungültiger Fehlercode %d.\n", ErrorCode); + } + } + return Result; +} + +int TQueryManagerConnection::logoutGame(uint32 CharacterID, int Level, const char *Profession, + const char *Residence, time_t LastLoginTime, int TutorActivities){ + this->prepareQuery(21); + this->sendQuad(CharacterID); + this->sendWord(Level); + this->sendString(Profession); + this->sendString(Residence); + this->sendQuad((uint32)LastLoginTime); + this->sendWord((uint16)TutorActivities); + int Status = this->executeQuery(120, true); + return (Status == QUERY_OK ? 0 : -1); +} + +int TQueryManagerConnection::setNotation(uint32 GamemasterID, const char *PlayerName, + const char *IPAddress, const char *Reason, const char *Comment, uint32 *BanishmentID){ + this->prepareQuery(26); + this->sendQuad(GamemasterID); + this->sendString(PlayerName); + this->sendString(IPAddress); + this->sendString(Reason); + this->sendString(Comment); + int Status = this->executeQuery(30, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_OK){ + *BanishmentID = this->getQuad(); + }else if(Status == QUERY_ERROR){ + int ErrorCode = this->getByte(); + if(ErrorCode >= 1 && ErrorCode <= 2){ + Result = ErrorCode; + }else{ + error("TQueryManagerConnection::setNotation: Ungültiger Fehlercode %d.\n", ErrorCode); + } + }else{ + error("TQueryManagerConnection::setNotation: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::setNamelock(uint32 GamemasterID, const char *PlayerName, + const char *IPAddress, const char *Reason, const char *Comment){ + this->prepareQuery(23); + this->sendQuad(GamemasterID); + this->sendString(PlayerName); + this->sendString(IPAddress); + this->sendString(Reason); + this->sendString(Comment); + int Status = this->executeQuery(30, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_ERROR){ + int ErrorCode = this->getByte(); + if(ErrorCode >= 1 && ErrorCode <= 4){ + Result = ErrorCode; + }else{ + error("TQueryManagerConnection::setNamelock: Ungültiger Fehlercode %d.\n", ErrorCode); + } + }else if(Status != QUERY_OK){ + error("TQueryManagerConnection::setNamelock: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::banishAccount(uint32 GamemasterID, const char *PlayerName, + const char *IPAddress, const char *Reason, const char *Comment, bool *FinalWarning, + int *Days, uint32 *BanishmentID){ + this->prepareQuery(25); + this->sendQuad(GamemasterID); + this->sendString(PlayerName); + this->sendString(IPAddress); + this->sendString(Reason); + this->sendString(Comment); + this->sendFlag(*FinalWarning); + int Status = this->executeQuery(30, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_OK){ + *BanishmentID = this->getQuad(); + *Days = this->getByte(); + *FinalWarning = this->getFlag(); + if(*Days == 0xFF){ + *Days = -1; + } + }else if(Status == QUERY_ERROR){ + int ErrorCode = this->getByte(); + if(ErrorCode >= 1 && ErrorCode <= 3){ + Result = ErrorCode; + }else{ + error("TQueryManagerConnection::banishAccount: Ungültiger Fehlercode %d.\n", ErrorCode); + } + }else{ + error("TQueryManagerConnection::banishAccount: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::reportStatement(uint32 ReporterID, const char *PlayerName, + const char *Reason, const char *Comment, uint32 BanishmentID, uint32 StatementID, + int NumberOfStatements, uint32 *StatementIDs, int *TimeStamps, uint32 *CharacterIDs, + const char (*Channels)[30], const char (*Texts)[256]){ + this->prepareQuery(27); + this->sendQuad(ReporterID); + this->sendString(PlayerName); + this->sendString(Reason); + this->sendString(Comment); + this->sendQuad(BanishmentID); + this->sendQuad(StatementID); + + int NonZeroStatements = 0; + for(int i = 0; i < NumberOfStatements; i += 1){ + if(StatementIDs[i] != 0){ + NonZeroStatements += 1; + } + } + + this->sendQuad((uint32)NonZeroStatements); + for(int i = 0; i < NumberOfStatements; i += 1){ + if(StatementIDs[i] != 0){ + this->sendQuad(StatementIDs[i]); + this->sendQuad((uint32)TimeStamps[i]); + this->sendQuad(CharacterIDs[i]); + this->sendString(Channels[i]); + this->sendString(Texts[i]); + } + } + + int Status = this->executeQuery(180, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_ERROR){ + int ErrorCode = this->getByte(); + if(ErrorCode >= 1 && ErrorCode <= 2){ + Result = ErrorCode; + }else{ + error("TQueryManagerConnection::reportStatement: Ungültiger Fehlercode %d.\n", ErrorCode); + } + }else if(Status != QUERY_OK){ + error("TQueryManagerConnection::reportStatement: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::banishIPAddress(uint32 GamemasterID, const char *PlayerName, + const char *IPAddress, const char *Reason, const char *Comment){ + this->prepareQuery(28); + this->sendQuad(GamemasterID); + this->sendString(PlayerName); + this->sendString(IPAddress); + this->sendString(Reason); + this->sendString(Comment); + int Status = this->executeQuery(30, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_ERROR){ + int ErrorCode = this->getByte(); + if(ErrorCode >= 1 && ErrorCode <= 2){ + Result = ErrorCode; + }else{ + error("TQueryManagerConnection::banishIPAddress: Ungültiger Fehlercode %d.\n", ErrorCode); + } + }else if(Status != QUERY_OK){ + error("TQueryManagerConnection::banishIPAddress: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::logCharacterDeath(uint32 CharacterID, int Level, + uint32 Offender, const char *Remark, bool Unjustified, time_t Time){ + this->prepareQuery(29); + this->sendQuad(CharacterID); + this->sendWord((uint16)Level); + this->sendQuad(Offender); + this->sendString(Remark); + this->sendFlag(Unjustified); + this->sendQuad((uint32)Time); + int Status = this->executeQuery(90, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status != QUERY_OK){ + error("TQueryManagerConnection::logCharacterDeath: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::addBuddy(uint32 AccountID, uint32 Buddy){ + this->prepareQuery(30); + this->sendQuad(AccountID); + this->sendQuad(Buddy); + int Status = this->executeQuery(90, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status != QUERY_OK){ + error("TQueryManagerConnection::addBuddy: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::removeBuddy(uint32 AccountID, uint32 Buddy){ + this->prepareQuery(31); + this->sendQuad(AccountID); + this->sendQuad(Buddy); + int Status = this->executeQuery(90, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status != QUERY_OK){ + error("TQueryManagerConnection::removeBuddy: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::decrementIsOnline(uint32 CharacterID){ + this->prepareQuery(32); + this->sendQuad(CharacterID); + int Status = this->executeQuery(30, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status != QUERY_OK){ + error("TQueryManagerConnection::decrementIsOnline: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::finishAuctions(int *NumberOfAuctions, uint16 *HouseIDs, + uint32 *CharacterIDs, char (*CharacterNames)[30], int *Bids){ + this->prepareQuery(33); + int Status = this->executeQuery(60, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_OK){ + int MaxNumberOfAuctions = *NumberOfAuctions; + *NumberOfAuctions = this->getWord(); + if(*NumberOfAuctions > MaxNumberOfAuctions){ + error("TQueryManagerConnection::finishAuctions: zu viele Auktionen (%d>%d).\n", + *NumberOfAuctions, MaxNumberOfAuctions); + return -1; + } + + for(int i = 0; i < *NumberOfAuctions; i += 1){ + HouseIDs[i] = this->getWord(); + CharacterIDs[i] = this->getQuad(); + this->getString(CharacterNames[i], 30); + Bids[i] = (int)this->getQuad(); + } + }else{ + error("TQueryManagerConnection::finishAuctions: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::excludeFromAuctions(uint32 CharacterID, bool Banish){ + this->prepareQuery(51); + this->sendQuad(CharacterID); + this->sendFlag(Banish); + int Status = this->executeQuery(30, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status != QUERY_OK){ + error("TQueryManagerConnection::excludeFromAuctions: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::transferHouses(int *NumberOfTransfers, uint16 *HouseIDs, + uint32 *NewOwnerIDs, char (*NewOwnerNames)[30], int *Prices){ + this->prepareQuery(35); + int Status = this->executeQuery(60, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_OK){ + int MaxNumberOfTransfers = *NumberOfTransfers; + *NumberOfTransfers = this->getWord(); + if(*NumberOfTransfers > MaxNumberOfTransfers){ + error("TQueryManagerConnection::transferHouses: zu viele Transfers (%d>%d).\n", + *NumberOfTransfers, MaxNumberOfTransfers); + return -1; + } + + for(int i = 0; i < *NumberOfTransfers; i += 1){ + HouseIDs[i] = this->getWord(); + NewOwnerIDs[i] = this->getQuad(); + this->getString(NewOwnerNames[i], 30); + Prices[i] = (int)this->getQuad(); + } + }else{ + error("TQueryManagerConnection::transferHouses: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::cancelHouseTransfer(uint16 HouseID){ + this->prepareQuery(52); + this->sendWord(HouseID); + int Status = this->executeQuery(30, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status != QUERY_OK){ + error("TQueryManagerConnection::cancelHouseTransfer: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::evictFreeAccounts(int *NumberOfEvictions, + uint16 *HouseIDs, uint32 *OwnerIDs){ + this->prepareQuery(36); + int Status = this->executeQuery(60, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_OK){ + int MaxNumberOfEvictions = *NumberOfEvictions; + *NumberOfEvictions = this->getWord(); + if(*NumberOfEvictions > MaxNumberOfEvictions){ + error("TQueryManagerConnection::evictFreeAccounts: zu viele Räumungen (%d>%d).\n", + *NumberOfEvictions, MaxNumberOfEvictions); + return -1; + } + + for(int i = 0; i < *NumberOfEvictions; i += 1){ + HouseIDs[i] = this->getWord(); + OwnerIDs[i] = this->getQuad(); + } + }else{ + error("TQueryManagerConnection::evictFreeAccounts: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::evictDeletedCharacters(int *NumberOfEvictions, uint16 *HouseIDs){ + this->prepareQuery(37); + int Status = this->executeQuery(60, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_OK){ + int MaxNumberOfEvictions = *NumberOfEvictions; + *NumberOfEvictions = this->getWord(); + if(*NumberOfEvictions > MaxNumberOfEvictions){ + error("TQueryManagerConnection::evictDeletedCharacters: zu viele Räumungen (%d>%d).\n", + *NumberOfEvictions, MaxNumberOfEvictions); + return -1; + } + + for(int i = 0; i < *NumberOfEvictions; i += 1){ + HouseIDs[i] = this->getWord(); + } + }else{ + error("TQueryManagerConnection::evictDeletedCharacters: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::evictExGuildleaders(int NumberOfGuildhouses, + int *NumberOfEvictions, uint16 *HouseIDs, uint32 *Guildleaders){ + this->prepareQuery(38); + + this->sendWord((uint16)NumberOfGuildhouses); + for(int i = 0; i < NumberOfGuildhouses; i += 1){ + this->sendWord(HouseIDs[i]); + this->sendQuad(Guildleaders[i]); + } + + int Status = this->executeQuery(60, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_OK){ + *NumberOfEvictions = this->getWord(); + for(int i = 0; i < *NumberOfEvictions; i += 1){ + HouseIDs[i] = this->getWord(); + } + }else{ + error("TQueryManagerConnection::evictExGuildleaders: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::insertHouseOwner(uint16 HouseID, uint32 OwnerID, int PaidUntil){ + this->prepareQuery(39); + this->sendWord(HouseID); + this->sendQuad(OwnerID); + this->sendQuad((uint32)PaidUntil); + int Status = this->executeQuery(30, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status != QUERY_OK){ + error("TQueryManagerConnection::insertHouseOwner: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::updateHouseOwner(uint16 HouseID, uint32 OwnerID, int PaidUntil){ + this->prepareQuery(40); + this->sendWord(HouseID); + this->sendQuad(OwnerID); + this->sendQuad((uint32)PaidUntil); + int Status = this->executeQuery(30, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status != QUERY_OK){ + error("TQueryManagerConnection::updateHouseOwner: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::deleteHouseOwner(uint16 HouseID){ + this->prepareQuery(41); + this->sendWord(HouseID); + int Status = this->executeQuery(30, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status != QUERY_OK){ + error("TQueryManagerConnection::deleteHouseOwner: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::getHouseOwners(int *NumberOfOwners, uint16 *HouseIDs, + uint32 *OwnerIDs, char (*OwnerNames)[30], int *PaidUntils){ + this->prepareQuery(42); + int Status = this->executeQuery(60, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_OK){ + int MaxNumberOfOwners = *NumberOfOwners; + *NumberOfOwners = this->getWord(); + if(*NumberOfOwners > MaxNumberOfOwners){ + error("TQueryManagerConnection::getHouseOwners: zu viele Häuser (%d>%d).\n", + *NumberOfOwners, MaxNumberOfOwners); + return -1; + } + + for(int i = 0; i < *NumberOfOwners; i += 1){ + HouseIDs[i] = this->getWord(); + OwnerIDs[i] = this->getQuad(); + this->getString(OwnerNames[i], 30); + PaidUntils[i] = (int)this->getQuad(); + } + }else{ + error("TQueryManagerConnection::getHouseOwners: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::getAuctions(int *NumberOfAuctions, uint16 *HouseIDs){ + this->prepareQuery(43); + int Status = this->executeQuery(120, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_OK){ + int MaxNumberOfAuctions = *NumberOfAuctions; + *NumberOfAuctions = this->getWord(); + if(*NumberOfAuctions > MaxNumberOfAuctions){ + error("TQueryManagerConnection::getAuctions: zu viele Auktionen (%d>%d).\n", + *NumberOfAuctions, MaxNumberOfAuctions); + return -1; + } + + for(int i = 0; i < *NumberOfAuctions; i += 1){ + HouseIDs[i] = this->getWord(); + } + }else{ + error("TQueryManagerConnection::getAuctions: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::startAuction(uint16 HouseID){ + this->prepareQuery(44); + this->sendWord(HouseID); + int Status = this->executeQuery(30, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status != QUERY_OK){ + error("TQueryManagerConnection::startAuction: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::insertHouses(int NumberOfHouses, uint16 *HouseIDs, + const char **Names, int *Rents, const char **Descriptions, int *Sizes, + int *PositionsX,int *PositionsY,int *PositionsZ, char (*Towns)[30], + bool *Guildhouses){ + this->prepareQuery(45); + + this->sendWord(NumberOfHouses); + for(int i = 0; i < NumberOfHouses; i += 1){ + this->sendWord(HouseIDs[i]); + this->sendString(Names[i]); + this->sendQuad((int)Rents[i]); + this->sendString(Descriptions[i]); + this->sendWord((uint16)Sizes[i]); + this->sendWord((uint16)PositionsX[i]); + this->sendWord((uint16)PositionsY[i]); + this->sendByte((uint8)PositionsZ[i]); + this->sendString(Towns[i]); + this->sendFlag(Guildhouses[i]); + } + + int Status = this->executeQuery(60, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status != QUERY_OK){ + error("TQueryManagerConnection::insertHouses: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::clearIsOnline(int *NumberOfAffectedPlayers){ + this->prepareQuery(46); + int Status = this->executeQuery(120, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_OK){ + *NumberOfAffectedPlayers = this->getWord(); + }else{ + error("TQueryManagerConnection::clearIsOnline: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::createPlayerlist(int NumberOfPlayers, const char **Names, + int *Levels, const char (*Professions)[30], bool *NewRecord){ + this->prepareQuery(47); + + if(NumberOfPlayers >= 0){ + this->sendWord((uint16)NumberOfPlayers); + for(int i = 0; i < NumberOfPlayers; i += 1){ + this->sendString(Names[i]); + this->sendWord((uint16)Levels[i]); + this->sendString(Professions[i]); + } + }else{ + this->sendWord(0xFFFF); + } + + int Status = this->executeQuery(240, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_OK){ + *NewRecord = this->getFlag(); + }else{ + error("TQueryManagerConnection::createPlayerlist: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::logKilledCreatures(int NumberOfRaces, const char **Names, + int *KilledPlayers,int *KilledCreatures){ + this->prepareQuery(48); + + this->sendWord((uint16)NumberOfRaces); + for(int i = 0; i < NumberOfRaces; i += 1){ + this->sendString(Names[i]); + this->sendQuad((uint32)KilledPlayers[i]); + this->sendQuad((uint32)KilledCreatures[i]); + } + + int Status = this->executeQuery(240, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status != QUERY_OK){ + error("TQueryManagerConnection::logKilledCreatures: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::loadPlayers(uint32 MinimumCharacterID, int *NumberOfPlayers, + char (*Names)[30], uint32 *CharacterIDs){ + this->prepareQuery(50); + this->sendQuad(MinimumCharacterID); + int Status = this->executeQuery(900, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_OK){ + // TODO(fusion): This is called to fill the player index in `InitPlayerIndex` + // but there is no explicit parameter that limits how many results are returned + // which could be a problem. + *NumberOfPlayers = (int)this->getQuad(); + for(int i = 0; i < *NumberOfPlayers; i += 1){ + this->getString(Names[i], 30); + CharacterIDs[i] = this->getQuad(); + } + }else{ + error("TQueryManagerConnection::loadPlayers: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::getKeptCharacters(uint32 MinimumCharacterID, + int *NumberOfPlayers, uint32 *CharacterIDs){ + this->prepareQuery(200); + this->sendQuad(MinimumCharacterID); + int Status = this->executeQuery(1800, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_OK){ + // TODO(fusion): Same as `loadPlayers`. + *NumberOfPlayers = (int)this->getQuad(); + for(int i = 0; i < *NumberOfPlayers; i += 1){ + CharacterIDs[i] = this->getQuad(); + } + }else{ + error("TQueryManagerConnection::getKeptCharacters: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::getDeletedCharacters(uint32 MinimumCharacterID, + int *NumberOfPlayers, uint32 *CharacterIDs){ + this->prepareQuery(201); + this->sendQuad(MinimumCharacterID); + int Status = this->executeQuery(900, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_OK){ + // TODO(fusion): Same as `loadPlayers`. + *NumberOfPlayers = (int)this->getQuad(); + for(int i = 0; i < *NumberOfPlayers; i += 1){ + CharacterIDs[i] = this->getQuad(); + } + }else{ + error("TQueryManagerConnection::getKeptCharacters: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::deleteOldCharacter(uint32 CharacterID){ + this->prepareQuery(202); + this->sendQuad(CharacterID); + int Status = this->executeQuery(30, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status != QUERY_OK){ + error("TQueryManagerConnection::deleteOldCharacter: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::getHiddenCharacters(uint32 MinimumCharacterID, + int *NumberOfPlayers, uint32 *CharacterIDs){ + this->prepareQuery(203); + this->sendQuad(MinimumCharacterID); + int Status = this->executeQuery(120, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_OK){ + // TODO(fusion): Same as `loadPlayers`. + *NumberOfPlayers = (int)this->getQuad(); + for(int i = 0; i < *NumberOfPlayers; i += 1){ + CharacterIDs[i] = this->getQuad(); + } + }else{ + error("TQueryManagerConnection::getHiddenCharacters: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::createHighscores(int NumberOfPlayers, uint32 *CharacterIDs, + int *ExpPoints, int *ExpLevel, int *Fist, int *Club, int *Axe, + int *Sword, int *Distance, int *Shielding, int *Magic, int *Fishing){ + this->prepareQuery(204); + + this->sendQuad((uint32)NumberOfPlayers); + for(int i = 0; i < NumberOfPlayers; i += 1){ + this->sendQuad(CharacterIDs[i]); + this->sendQuad((uint32)ExpPoints[i]); + this->sendWord((uint16)ExpLevel[i]); + this->sendWord((uint16)Fist[i]); + this->sendWord((uint16)Club[i]); + this->sendWord((uint16)Axe[i]); + this->sendWord((uint16)Sword[i]); + this->sendWord((uint16)Distance[i]); + this->sendWord((uint16)Shielding[i]); + this->sendWord((uint16)Magic[i]); + this->sendWord((uint16)Fishing[i]); + } + + int Status = this->executeQuery(120, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status != QUERY_OK){ + error("TQueryManagerConnection::createHighscores: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::createCensus(void){ + this->prepareQuery(205); + int Status = this->executeQuery(600, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status != QUERY_OK){ + error("TQueryManagerConnection::createCensus: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::createKillStatistics(void){ + this->prepareQuery(206); + int Status = this->executeQuery(300, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status != QUERY_OK){ + error("TQueryManagerConnection::createKillStatistics: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::getPlayersOnline(int *NumberOfWorlds, char (*Names)[30], uint16 *Players){ + this->prepareQuery(207); + int Status = this->executeQuery(120, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_OK){ + *NumberOfWorlds = this->getByte(); + for(int i = 0; i < *NumberOfWorlds; i += 1){ + this->getString(Names[i], 30); + Players[i] = this->getWord(); + } + }else{ + error("TQueryManagerConnection::getPlayersOnline: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::getWorlds(int *NumberOfWorlds, char (*Names)[30]){ + this->prepareQuery(208); + int Status = this->executeQuery(120, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_OK){ + *NumberOfWorlds = this->getByte(); + for(int i = 0; i < *NumberOfWorlds; i += 1){ + this->getString(Names[i], 30); + } + }else{ + error("TQueryManagerConnection::getWorlds: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::getServerLoad(const char *World, int Period, int *Data){ + this->prepareQuery(209); + this->sendString(World); + this->sendByte((uint8)Period); + int Status = this->executeQuery(360, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_OK){ + // TODO(fusion): Another hardcoded constant? + for(int i = 0; i < 600; i += 0){ + Data[i] = this->getWord(); + if(Data[i] == 0xFFFF){ + Data[i] = -1; + } + } + }else{ + error("TQueryManagerConnection::getServerLoad: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::insertPaymentDataOld(uint32 PurchaseNr, uint32 ReferenceNr, + const char *FirstName, const char *LastName, const char *Company, + const char *Street, const char *Zip, const char *City, const char *Country, + const char *State, const char *Phone, const char *Fax, const char *EMail, + const char *PaymentMethod, uint32 ProductID, const char *Registrant, + uint32 AccountID, uint32 *PaymentID){ + this->prepareQuery(210); + this->sendQuad(PurchaseNr); + this->sendQuad(ReferenceNr); + this->sendString(FirstName); + this->sendString(LastName); + this->sendString(Company); + this->sendString(Street); + this->sendString(Zip); + this->sendString(City); + this->sendString(Country); + this->sendString(State); + this->sendString(Phone); + this->sendString(Fax); + this->sendString(EMail); + this->sendString(PaymentMethod); + this->sendQuad(ProductID); + this->sendString(Registrant); + this->sendQuad(AccountID); + int Status = this->executeQuery(360, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_OK){ + *PaymentID = this->getQuad(); + }else if(Status == QUERY_ERROR){ + int ErrorCode = this->getByte(); + if(ErrorCode == 1){ + Result = ErrorCode; + }else{ + error("TQueryManagerConnection::insertPaymentDataOld: Ungültiger Fehlercode %d.\n", ErrorCode); + } + }else{ + error("TQueryManagerConnection::insertPaymentDataOld: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::addPaymentOld(uint32 AccountID, const char *Description, + uint32 PaymentID, int Days, int *ActionTaken){ + this->prepareQuery(211); + this->sendQuad(AccountID); + this->sendString(Description); + this->sendQuad(PaymentID); + this->sendWord((uint16)Days); + int Status = this->executeQuery(360, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_OK){ + *ActionTaken = this->getByte(); + }else if(Status == QUERY_ERROR){ + int ErrorCode = this->getByte(); + if(ErrorCode >= 1 && ErrorCode <= 2){ + Result = ErrorCode; + }else{ + error("TQueryManagerConnection::addPaymentOld: Ungültiger Fehlercode %d.\n", ErrorCode); + } + }else{ + error("TQueryManagerConnection::addPaymentOld: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::cancelPaymentOld(uint32 PurchaseNr, uint32 ReferenceNr, + uint32 AccountID, bool *IllegalUse, char *EMailAddress){ + this->prepareQuery(212); + this->sendQuad(PurchaseNr); + this->sendQuad(ReferenceNr); + this->sendQuad(AccountID); + int Status = this->executeQuery(360, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_OK){ + *IllegalUse = this->getFlag(); + this->getString(EMailAddress, 50); + }else if(Status == QUERY_ERROR){ + int ErrorCode = this->getByte(); + if(ErrorCode >= 1 && ErrorCode <= 2){ + Result = ErrorCode; + }else{ + error("TQueryManagerConnection::cancelPaymentOld: Ungültiger Fehlercode %d.\n", ErrorCode); + } + }else{ + error("TQueryManagerConnection::cancelPaymentOld: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::insertPaymentDataNew(uint32 PurchaseNr, uint32 ReferenceNr, + const char *FirstName, const char *LastName, const char *Company, + const char *Street, const char *Zip, const char *City, const char *Country, + const char *State, const char *Phone, const char *Fax, const char *EMail, + const char *PaymentMethod, uint32 ProductID, const char *Registrant, + const char *PaymentKey, uint32 *PaymentID){ + this->prepareQuery(213); + this->sendWord(PurchaseNr); + this->sendWord(ReferenceNr); + this->sendString(FirstName); + this->sendString(LastName); + this->sendString(Company); + this->sendString(Street); + this->sendString(Zip); + this->sendString(City); + this->sendString(Country); + this->sendString(State); + this->sendString(Phone); + this->sendString(Fax); + this->sendString(EMail); + this->sendString(PaymentMethod); + this->sendWord(ProductID); + this->sendString(Registrant); + this->sendString(PaymentKey); + int Status = this->executeQuery(360, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_OK){ + *PaymentID = this->getQuad(); + }else if(Status == QUERY_ERROR){ + int ErrorCode = this->getByte(); + if(ErrorCode == 1){ + Result = ErrorCode; + }else{ + error("TQueryManagerConnection::insertPaymentDataNew: Ungültiger Fehlercode %d.\n", ErrorCode); + } + }else{ + error("TQueryManagerConnection::insertPaymentDataNew: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::addPaymentNew(const char *PaymentKey, uint32 PaymentID, + int *ActionTaken, char *EMailReceiver){ + this->prepareQuery(214); + this->sendString(PaymentKey); + this->sendQuad(PaymentID); + int Status = this->executeQuery(360, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_OK){ + *ActionTaken = this->getByte(); + if(*ActionTaken == 5){ + this->getString(EMailReceiver, 100); + } + }else if(Status == QUERY_ERROR){ + int ErrorCode = this->getByte(); + if(ErrorCode >= 1 && ErrorCode <= 3){ + Result = ErrorCode; + }else{ + error("TQueryManagerConnection::addPaymentNew: Ungültiger Fehlercode %d.\n", ErrorCode); + } + }else{ + error("TQueryManagerConnection::addPaymentNew: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +int TQueryManagerConnection::cancelPaymentNew(uint32 PurchaseNr, uint32 ReferenceNr, + const char *PaymentKey, bool *IllegalUse, bool *Present, char *EMailAddress){ + this->prepareQuery(215); + this->sendQuad(PurchaseNr); + this->sendQuad(ReferenceNr); + this->sendString(PaymentKey); + int Status = this->executeQuery(360, true); + int Result = (Status == QUERY_OK ? 0 : -1); + if(Status == QUERY_OK){ + *IllegalUse = this->getFlag(); + *Present = this->getFlag(); + this->getString(EMailAddress, 50); + }else if(Status == QUERY_ERROR){ + int ErrorCode = this->getByte(); + if(ErrorCode == 1){ + Result = ErrorCode; + }else{ + error("TQueryManagerConnection::cancelPaymentNew: Ungültiger Fehlercode %d.\n", ErrorCode); + } + }else{ + error("TQueryManagerConnection::cancelPaymentNew: Anfrage fehlgeschlagen.\n"); + } + return Result; +} + +// TQueryManagerConnectionPool +// ============================================================================= +// TODO(fusion): Same as `TQueryManagerConnection::TQueryManagerConnection`. +TQueryManagerConnectionPool::TQueryManagerConnectionPool(int Connections) : + NumberOfConnections(std::max<int>(Connections, 1)), + QueryManagerConnection(NULL), + QueryManagerConnectionFree(NULL), + FreeQueryManagerConnections(this->NumberOfConnections), + QueryManagerConnectionMutex(1) +{ + if(Connections <= 0){ + error("TQueryManagerConnectionPool::TQueryManagerConnectionPool:" + " Ungültige Verbindungsanzahl %d.\n", Connections); + } +} + +void TQueryManagerConnectionPool::init(void){ + this->QueryManagerConnection = new TQueryManagerConnection[this->NumberOfConnections]; + this->QueryManagerConnectionFree = new bool[this->NumberOfConnections]; + for(int i = 0; i < this->NumberOfConnections; i += 1){ + if(!this->QueryManagerConnection[i].isConnected()){ + error("TQueryManagerConnectionPool::init: Kann nicht zum Query-Manager verbinden.\n"); + throw "cannot connect to query manager"; + } + + this->QueryManagerConnectionFree[i] = true; + } +} + +void TQueryManagerConnectionPool::exit(void){ + for(int i = 0; i < this->NumberOfConnections; i += 1){ + this->FreeQueryManagerConnections.down(); + } + + delete[] this->QueryManagerConnection; + delete[] this->QueryManagerConnectionFree; +} + +TQueryManagerConnection *TQueryManagerConnectionPool::getConnection(void){ + int ConnectionIndex = -1; + this->FreeQueryManagerConnections.down(); + this->QueryManagerConnectionMutex.down(); + for(int i = 0; i < this->NumberOfConnections; i += 1){ + if(this->QueryManagerConnectionFree[i]){ + this->QueryManagerConnectionFree[i] = false; + ConnectionIndex = i; + break; + } + } + this->QueryManagerConnectionMutex.up(); + + if(ConnectionIndex == -1){ + error("TQueryManagerConnectionPool::getConnection: Keine freie Verbindung gefunden.\n"); + return NULL; + } + + return &this->QueryManagerConnection[ConnectionIndex]; +} + +void TQueryManagerConnectionPool::releaseConnection(TQueryManagerConnection *Connection){ + int ConnectionIndex = -1; + for(int i = 0; i < this->NumberOfConnections; i += 1){ + if(&this->QueryManagerConnection[i] == Connection){ + ConnectionIndex = i; + break; + } + } + + if(ConnectionIndex == -1){ + error("TQueryManagerConnectionPool::releaseConnection: Verbindung nicht gefunden.\n"); + return; + } + + this->QueryManagerConnectionFree[ConnectionIndex] = true; + this->FreeQueryManagerConnections.up(); +} + +// TQueryManagerPoolConnection +// ============================================================================= +TQueryManagerPoolConnection::TQueryManagerPoolConnection(TQueryManagerConnectionPool *Pool) : + QueryManagerConnectionPool(Pool), + QueryManagerConnection(NULL) +{ + if(this->QueryManagerConnectionPool == NULL){ + error("TQueryManagerPoolConnection::TQueryManagerPoolConnection: Pool ist NULL.\n"); + return; + } + + this->QueryManagerConnection = this->QueryManagerConnectionPool->getConnection(); +} + +TQueryManagerPoolConnection::~TQueryManagerPoolConnection(void){ + if(this->QueryManagerConnection != NULL){ + ASSERT(this->QueryManagerConnectionPool != NULL); + this->QueryManagerConnectionPool->releaseConnection(this->QueryManagerConnection); + } +} diff --git a/src/query.hh b/src/query.hh index 8bdd527..dbba9dc 100644 --- a/src/query.hh +++ b/src/query.hh @@ -11,6 +11,7 @@ enum : int { }; struct TQueryManagerConnection{ + TQueryManagerConnection(void) : TQueryManagerConnection(KB(16)) {} TQueryManagerConnection(int QueryBufferSize); ~TQueryManagerConnection(void); @@ -39,35 +40,20 @@ struct TQueryManagerConnection{ int executeQuery(int Timeout, bool AutoReconnect); -//== - - int loadWorldConfig(int *WorldType, int *RebootTime, - int *IPAddress, int *Port, - int *MaxPlayers, int *PremiumPlayerBuffer, - int *MaxNewbies, int *PremiumNewbieBuffer); - int loadPlayers(uint32 MinimumCharacterID, int *NumberOfPlayers, - char (*Names)[30], uint32 *CharacterIDs); - - int loginGame(uint32 AccountID, const char *PlayerName, const char *Password, + int checkAccountPassword(uint32 AccountID, const char *Password, const char *IPAddress); + int loginAdmin(uint32 AccountID, bool PrivateWorld, int *NumberOfCharacters, + char (*Characters)[30], char (*Worlds)[30], uint8 (*IPAddresses)[4], + uint16 *Ports, uint16 *PremiumDaysLeft); + int loadWorldConfig(int *WorldType, int *RebootTime, int *IPAddress, + int *Port, int *MaxPlayers, int *PremiumPlayerBuffer, int *MaxNewbies, + int *PremiumNewbieBuffer); + int loginGame(uint32 AccountID, char *PlayerName, const char *Password, const char *IPAddress, bool PrivateWorld, bool PremiumAccountRequired, bool GamemasterRequired, uint32 *CharacterID, int *Sex, char *Guild, char *Rank, char *Title, int *NumberOfBuddies, uint32 *BuddyIDs, char (*BuddyNames)[30], uint8 *Rights, bool *PremiumAccountActivated); int logoutGame(uint32 CharacterID, int Level, const char *Profession, const char *Residence, time_t LastLoginTime, int TutorActivities); - int createPlayerlist(int NumberOfPlayers, const char **Names, int *Levels, - const char (*Professions)[30], bool *NewRecord); - int decrementIsOnline(uint32 CharacterID); - int clearIsOnline(int *NumberOfAffectedPlayers); - int addBuddy(uint32 AccountID, uint32 BuddyID); - int removeBuddy(uint32 AccountID, uint32 BuddyID); - - int logKilledCreatures(int NumberOfRaces, const char **Names, - int *KilledPlayers,int *KilledCreatures); - - int logCharacterDeath(uint32 CharacterID, int Level, uint32 OffenderID, - const char *Remark, bool Unjustified, time_t Time); - int setNotation(uint32 GamemasterID, const char *PlayerName, const char *IPAddress, const char *Reason, const char *Comment, uint32 *BanishmentID); int setNamelock(uint32 GamemasterID, const char *PlayerName, const char *IPAddress, @@ -76,35 +62,82 @@ struct TQueryManagerConnection{ const char *Reason, const char *Comment, bool *FinalWarning, int *Days, uint32 *BanishmentID); int reportStatement(uint32 ReporterID, const char *PlayerName, const char *Reason, - const char *Comment, uint32 BanishmentID, uint32 StatementID, int NumberOfStatements, - uint32 *StatementIDs, int *TimeStamps, uint32 *CharacterIDs, char (*Channels)[30], - char (*Texts)[256]); + const char *Comment, uint32 BanishmentID, uint32 StatementID, + int NumberOfStatements, uint32 *StatementIDs, int *TimeStamps, + uint32 *CharacterIDs, const char (*Channels)[30], const char (*Texts)[256]); int banishIPAddress(uint32 GamemasterID, const char *PlayerName, const char *IPAddress, const char *Reason, const char *Comment); - - int insertHouses(int NumberOfHouses, uint16 *HouseIDs, char **Names, - int *Rents, char **Descriptions, int *Sizes, int *PositionsX, - int *PositionsY, int *PositionsZ, char (*Towns)[30], bool *Guildhouses); - + int logCharacterDeath(uint32 CharacterID, int Level, uint32 Offender, + const char *Remark, bool Unjustified, time_t Time); + int addBuddy(uint32 AccountID, uint32 Buddy); + int removeBuddy(uint32 AccountID, uint32 Buddy); + int decrementIsOnline(uint32 CharacterID); int finishAuctions(int *NumberOfAuctions, uint16 *HouseIDs, uint32 *CharacterIDs, char (*CharacterNames)[30], int *Bids); - int excludeFromAuctions(uint32 CharacterIDs, bool Banish); - + int excludeFromAuctions(uint32 CharacterID, bool Banish); int transferHouses(int *NumberOfTransfers, uint16 *HouseIDs, - uint32 *NewOwnerIDs, char (*NewOwnerNames) [30], int *Prices); + uint32 *NewOwnerIDs, char (*NewOwnerNames)[30], int *Prices); int cancelHouseTransfer(uint16 HouseID); int evictFreeAccounts(int *NumberOfEvictions, uint16 *HouseIDs, uint32 *OwnerIDs); int evictDeletedCharacters(int *NumberOfEvictions, uint16 *HouseIDs); - int evictExGuildleaders(int NumberOfGuildhouses, int *NumberOfEvictions, - uint16 *HouseIDs, uint32 *Guildleaders); + int evictExGuildleaders(int NumberOfGuildhouses, + int *NumberOfEvictions, uint16 *HouseIDs, uint32 *Guildleaders); + int insertHouseOwner(uint16 HouseID, uint32 OwnerID, int PaidUntil); + int updateHouseOwner(uint16 HouseID, uint32 OwnerID, int PaidUntil); int deleteHouseOwner(uint16 HouseID); - + int getHouseOwners(int *NumberOfOwners, uint16 *HouseIDs, + uint32 *OwnerIDs, char (*OwnerNames)[30], int *PaidUntils); int getAuctions(int *NumberOfAuctions, uint16 *HouseIDs); int startAuction(uint16 HouseID); - int getHouseOwners(int *NumberOfHouses, uint16 *HouseIDs, - uint32 *OwnerIDs, char (*OwnerNames)[30], int *PaidUntils); - int insertHouseOwner(uint16 HouseID, uint32 OwnerID, int PaidUntil); - int updateHouseOwner(uint16 HouseID, uint32 OwnerID, int PaidUntil); + int insertHouses(int NumberOfHouses, uint16 *HouseIDs, + const char **Names, int *Rents, const char **Descriptions, + int *Sizes, int *PositionsX,int *PositionsY,int *PositionsZ, + char (*Towns)[30], bool *Guildhouses); + int clearIsOnline(int *NumberOfAffectedPlayers); + int createPlayerlist(int NumberOfPlayers, const char **Names, + int *Levels, const char (*Professions)[30], bool *NewRecord); + int logKilledCreatures(int NumberOfRaces, const char **Names, + int *KilledPlayers,int *KilledCreatures); + int loadPlayers(uint32 MinimumCharacterID, int *NumberOfPlayers, + char (*Names)[30], uint32 *CharacterIDs); + int getKeptCharacters(uint32 MinimumCharacterID, + int *NumberOfPlayers, uint32 *CharacterIDs); + int getDeletedCharacters(uint32 MinimumCharacterID, + int *NumberOfPlayers, uint32 *CharacterIDs); + int deleteOldCharacter(uint32 CharacterID); + int getHiddenCharacters(uint32 MinimumCharacterID, + int *NumberOfPlayers, uint32 *CharacterIDs); + int createHighscores(int NumberOfPlayers, uint32 *CharacterIDs, + int *ExpPoints, int *ExpLevel, int *Fist, int *Club, int *Axe, + int *Sword, int *Distance, int *Shielding, int *Magic, int *Fishing); + int createCensus(void); + int createKillStatistics(void); + int getPlayersOnline(int *NumberOfWorlds, char (*Names)[30], uint16 *Players); + int getWorlds(int *NumberOfWorlds, char (*Names)[30]); + int getServerLoad(const char *World, int Period, int *Data); + + int insertPaymentDataOld(uint32 PurchaseNr, uint32 ReferenceNr, + const char *FirstName, const char *LastName, const char *Company, + const char *Street, const char *Zip, const char *City, const char *Country, + const char *State, const char *Phone, const char *Fax, const char *EMail, + const char *PaymentMethod, uint32 ProductID, const char *Registrant, + uint32 AccountID, uint32 *PaymentID); + int addPaymentOld(uint32 AccountID, const char *Description, + uint32 PaymentID, int Days, int *ActionTaken); + int cancelPaymentOld(uint32 PurchaseNr, uint32 ReferenceNr, + uint32 AccountID, bool *IllegalUse, char *EMailAddress); + + int insertPaymentDataNew(uint32 PurchaseNr, uint32 ReferenceNr, + const char *FirstName, const char *LastName, const char *Company, + const char *Street, const char *Zip, const char *City, const char *Country, + const char *State, const char *Phone, const char *Fax, const char *EMail, + const char *PaymentMethod, uint32 ProductID, const char *Registrant, + const char *PaymentKey, uint32 *PaymentID); + int addPaymentNew(const char *PaymentKey, uint32 PaymentID, + int *ActionTaken, char *EMailReceiver); + int cancelPaymentNew(uint32 PurchaseNr, uint32 ReferenceNr, + const char *PaymentKey, bool *IllegalUse, bool *Present, + char *EMailAddress); // DATA // ================= @@ -120,6 +153,8 @@ struct TQueryManagerConnectionPool{ TQueryManagerConnectionPool(int Connections); void init(void); void exit(void); + TQueryManagerConnection *getConnection(void); + void releaseConnection(TQueryManagerConnection *Connection); // DATA // ================= |
