From 1268ecbc941d79f31868aaf996dca7b9f6ce39ff Mon Sep 17 00:00:00 2001 From: Emagi Date: Fri, 11 Apr 2025 09:49:18 -0400 Subject: [PATCH] Fix Issue #3 - Class Updates, Name Updates to LS Support added for class updates to LoginServer when adventure class is updated (such as commoner to sub class, so on). Name change for GM command /name support added for LS update. This is a use at your own risk command and you will have to /camp to fully reflect your name update. --- source/LoginServer/LWorld.cpp | 15 +++++++++++++++ source/LoginServer/LoginDatabase.cpp | 13 +++++++++++++ source/LoginServer/LoginDatabase.h | 1 + source/WorldServer/Commands/Commands.cpp | 8 +++++--- source/WorldServer/Player.cpp | 2 ++ source/WorldServer/WorldDatabase.cpp | 5 ++++- source/WorldServer/client.cpp | 12 +++++++++++- 7 files changed, 51 insertions(+), 5 deletions(-) diff --git a/source/LoginServer/LWorld.cpp b/source/LoginServer/LWorld.cpp index aa80ad4..6a79dbe 100644 --- a/source/LoginServer/LWorld.cpp +++ b/source/LoginServer/LWorld.cpp @@ -421,6 +421,21 @@ bool LWorld::Process() { } break; } + case ServerOP_NameCharUpdate: { + CharNameUpdate_Struct* cnu = (CharNameUpdate_Struct*) pack->pBuffer; + if (cnu->name_length > 0 && cnu->name_length < 64) { + char name_buffer[64]; + + // Copy up to name_length characters from cnu->new_name + strncpy(name_buffer, cnu->new_name, cnu->name_length); + + // Null-terminate the string just in case + name_buffer[cnu->name_length] = '\0'; + + database.UpdateCharacterName(cnu->account_id,cnu->char_id,name_buffer,this->GetAccountID()); + } + break; + } case ServerOP_LSInfo: { if (pack->size != sizeof(ServerLSInfo_Struct)) { this->Kick(ERROR_BADVERSION); diff --git a/source/LoginServer/LoginDatabase.cpp b/source/LoginServer/LoginDatabase.cpp index b750a62..80bfe98 100644 --- a/source/LoginServer/LoginDatabase.cpp +++ b/source/LoginServer/LoginDatabase.cpp @@ -617,6 +617,19 @@ bool LoginDatabase::UpdateCharacterGender(int32 account_id, int32 character_id, return true; } +bool LoginDatabase::UpdateCharacterName(int32 account_id, int32 character_id, char* newName, int32 server_id){ + Query query; + string update_charts = string("update login_characters set name='%s' where char_id=%lu and account_id=%lu and server_id=%lu"); + query.RunQuery2(Q_UPDATE, update_charts.c_str(),newName,character_id,account_id,server_id); + if(!query.GetAffectedRows()) + { + LogWrite(LOGIN__ERROR, 0, "Login", "Error in UpdateCharacterName query '%s': %s", query.GetQuery(), query.GetError()); + return false; + } + + return true; +} + LoginAccount* LoginDatabase::LoadAccount(const char* name, const char* password, bool attemptAccountCreation){ LoginAccount* acct = NULL; Query query; diff --git a/source/LoginServer/LoginDatabase.h b/source/LoginServer/LoginDatabase.h index 84f8d7b..27ba85b 100644 --- a/source/LoginServer/LoginDatabase.h +++ b/source/LoginServer/LoginDatabase.h @@ -59,6 +59,7 @@ public: bool UpdateCharacterLevel(int32 account_id, int32 character_id, int8 in_level, int32 server_id); bool UpdateCharacterRace(int32 account_id, int32 character_id, int16 in_racetype, int8 in_race, int32 server_id); bool UpdateCharacterClass(int32 account_id, int32 character_id, int8 in_class, int32 server_id); + bool UpdateCharacterName(int32 account_id, int32 character_id, char* newName, int32 server_id); bool UpdateCharacterZone(int32 account_id, int32 character_id, int32 zone_id, int32 server_id); bool UpdateCharacterGender(int32 account_id, int32 character_id, int8 in_gender, int32 server_id); int32 GetRaceID(char* name); diff --git a/source/WorldServer/Commands/Commands.cpp b/source/WorldServer/Commands/Commands.cpp index f50d124..bf53cdb 100644 --- a/source/WorldServer/Commands/Commands.cpp +++ b/source/WorldServer/Commands/Commands.cpp @@ -2896,7 +2896,6 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie case COMMAND_CLASS:{ if(sep && sep->arg[ndx][0]){ client->GetPlayer()->SetPlayerAdventureClass(atoi(sep->arg[ndx])); - client->UpdateTimeStampFlag ( CLASS_UPDATE_FLAG ); }else client->SimpleMessage(CHANNEL_COLOR_YELLOW,"Usage: /class {class_id}"); break; @@ -3205,9 +3204,12 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie break; } case COMMAND_NAME:{ - if(sep && sep->arg[ndx][0]){ - client->GetPlayer()->GetInfoStruct()->set_name(std::string(sep->arg[ndx]).substr(0,39)); + if(sep && sep->arg[0]){ + client->GetPlayer()->GetInfoStruct()->set_name(sep->argplus[0]); client->GetPlayer()->SetCharSheetChanged(true); + client->GetPlayer()->info_changed = true; + client->GetPlayer()->GetZone()->AddChangedSpawn(client->GetPlayer()); + client->UpdateTimeStampFlag ( NAME_UPDATE_FLAG ); }else client->Message(CHANNEL_COLOR_YELLOW,"Usage: /name {new_name}"); diff --git a/source/WorldServer/Player.cpp b/source/WorldServer/Player.cpp index f7afcc1..9bcccb3 100644 --- a/source/WorldServer/Player.cpp +++ b/source/WorldServer/Player.cpp @@ -6375,6 +6375,8 @@ void Player::SetPlayerAdventureClass(int8 new_class){ charsheet_changed = true; if(GetZone()) GetZone()->TriggerCharSheetTimer(); + if(GetClient()) + GetClient()->UpdateTimeStampFlag ( CLASS_UPDATE_FLAG ); } void Player::AddSkillBonus(int32 spell_id, int32 skill_id, float value) { diff --git a/source/WorldServer/WorldDatabase.cpp b/source/WorldServer/WorldDatabase.cpp index 1762eea..8b0280e 100644 --- a/source/WorldServer/WorldDatabase.cpp +++ b/source/WorldServer/WorldDatabase.cpp @@ -4391,7 +4391,10 @@ void WorldDatabase::Save(Client* client){ else if(client->GetCurrentZone()) zone_id = client->GetCurrentZone()->GetZoneID(); - query.AddQueryAsync(client->GetCharacterID(), this, Q_UPDATE, "update characters set current_zone_id=%u, x=%f, y=%f, z=%f, heading=%f, level=%i,instance_id=%i,last_saved=%i, `class`=%i, `tradeskill_level`=%i, `tradeskill_class`=%i, `group_id`=%u, deity = %u, alignment = %u, zone_duplicating_id = %u where id = %u", zone_id, player->GetX(), player->GetY(), player->GetZ(), player->GetHeading(), player->GetLevel(), instance_id, client->GetLastSavedTimeStamp(), client->GetPlayer()->GetAdventureClass(), client->GetPlayer()->GetTSLevel(), client->GetPlayer()->GetTradeskillClass(), client->GetPlayer()->GetGroupMemberInfo() ? client->GetPlayer()->GetGroupMemberInfo()->group_id : client->GetRejoinGroupID(), client->GetPlayer()->GetDeity(), client->GetPlayer()->GetInfoStruct()->get_alignment(), client->GetDuplicatingZoneID(), client->GetCharacterID()); + char charName[64]; + strncpy(charName, client->GetPlayer()->GetInfoStruct()->get_name().c_str(),64); + charName[63] = '\0'; + query.AddQueryAsync(client->GetCharacterID(), this, Q_UPDATE, "update characters set name='%s',current_zone_id=%u, x=%f, y=%f, z=%f, heading=%f, level=%i,instance_id=%i,last_saved=%i, `class`=%i, `tradeskill_level`=%i, `tradeskill_class`=%i, `group_id`=%u, deity = %u, alignment = %u, zone_duplicating_id = %u where id = %u", charName, zone_id, player->GetX(), player->GetY(), player->GetZ(), player->GetHeading(), player->GetLevel(), instance_id, client->GetLastSavedTimeStamp(), client->GetPlayer()->GetAdventureClass(), client->GetPlayer()->GetTSLevel(), client->GetPlayer()->GetTradeskillClass(), client->GetPlayer()->GetGroupMemberInfo() ? client->GetPlayer()->GetGroupMemberInfo()->group_id : client->GetRejoinGroupID(), client->GetPlayer()->GetDeity(), client->GetPlayer()->GetInfoStruct()->get_alignment(), client->GetDuplicatingZoneID(), client->GetCharacterID()); query.AddQueryAsync(client->GetCharacterID(), this, Q_UPDATE, "update character_details set hp=%u, power=%u, str=%i, sta=%i, agi=%i, wis=%i, intel=%i, heat=%i, cold=%i, magic=%i, mental=%i, divine=%i, disease=%i, poison=%i, coin_copper=%u, coin_silver=%u, coin_gold=%u, coin_plat=%u, max_hp = %u, max_power=%u, xp = %u, xp_needed = %u, xp_debt = %f, xp_vitality = %f, tradeskill_xp = %u, tradeskill_xp_needed = %u, tradeskill_xp_vitality = %f, bank_copper = %u, bank_silver = %u, bank_gold = %u, bank_plat = %u, status_points = %u, bind_zone_id=%u, bind_x = %f, bind_y = %f, bind_z = %f, bind_heading = %f, house_zone_id=%u, combat_voice = %i, emote_voice = %i, biography='%s', flags=%u, flags2=%u, last_name='%s', assigned_aa = %i, unassigned_aa = %i, tradeskill_aa = %i, unassigned_tradeskill_aa = %i, prestige_aa = %i, unassigned_prestige_aa = %i, tradeskill_prestige_aa = %i, unassigned_tradeskill_prestige_aa = %i, pet_name = '%s' where char_id = %u", player->GetHP(), player->GetPower(), player->GetStrBase(), player->GetStaBase(), player->GetAgiBase(), player->GetWisBase(), player->GetIntBase(), player->GetHeatResistanceBase(), player->GetColdResistanceBase(), player->GetMagicResistanceBase(), player->GetMentalResistanceBase(), player->GetDivineResistanceBase(), player->GetDiseaseResistanceBase(), player->GetPoisonResistanceBase(), player->GetCoinsCopper(), player->GetCoinsSilver(), player->GetCoinsGold(), player->GetCoinsPlat(), player->GetTotalHPBase(), player->GetTotalPowerBase(), player->GetXP(), player->GetNeededXP(), player->GetXPDebt(), player->GetXPVitality(), player->GetTSXP(), player->GetNeededTSXP(), player->GetTSXPVitality(), player->GetBankCoinsCopper(), diff --git a/source/WorldServer/client.cpp b/source/WorldServer/client.cpp index 708415c..72071b6 100644 --- a/source/WorldServer/client.cpp +++ b/source/WorldServer/client.cpp @@ -5181,7 +5181,17 @@ void Client::DetermineCharacterUpdates() { LogWrite(MISC__TODO, 1, "TODO", "Armor update req in func: %s, line: %i", __FUNCTION__, __LINE__); } if (flag & NAME_UPDATE_FLAG) { - LogWrite(MISC__TODO, 1, "TODO", "Name update req in func: %s, line: %i", __FUNCTION__, __LINE__); + int8 name_length = strnlen(GetPlayer()->GetInfoStruct()->get_name().c_str(), 64); // max of 64 to LS the DB limit + int32 packet_length = sizeof(CharNameUpdate_Struct) + name_length; + ServerPacket* outpack = new ServerPacket(ServerOP_NameCharUpdate, packet_length); + memset(outpack->pBuffer, 0, packet_length); + CharNameUpdate_Struct* cnu = (CharNameUpdate_Struct*)outpack->pBuffer; + cnu->account_id = GetAccountID(); + cnu->char_id = GetCharacterID(); + cnu->name_length = name_length; + strncpy(cnu->new_name, GetPlayer()->GetInfoStruct()->get_name().c_str(), name_length); + loginserver.SendPacket(outpack); + safe_delete(outpack); } database.UpdateCharacterTimeStamp(GetAccountID(), GetCharacterID(), timestamp);