feat: Remove PERSISTENT ObjectID bit because it's not an ObjectID bit (#1881)

* feat: Remove PERSISTENT ObjectID bit because it's not an ObjectID bit

TODO: Need to add character save migration for the pet subkey in the inventory
Tested that the migrations work on mysql and sqlite and that properties have all their contents as before.
Need to test pets still

* fix: ugc, pet ids. remove persistent bit
This commit is contained in:
David Markowitz
2025-09-22 21:41:38 -07:00
committed by GitHub
parent 4a5dd68e87
commit 64faac714c
16 changed files with 151 additions and 51 deletions

View File

@@ -82,6 +82,7 @@
#include "MissionComponent.h"
#include "SlashCommandHandler.h"
#include "InventoryComponent.h"
#include "Item.h"
namespace Game {
Logger* logger = nullptr;
@@ -1038,21 +1039,6 @@ void HandlePacket(Packet* packet) {
auto* characterComponent = player->GetComponent<CharacterComponent>();
if (!characterComponent) return;
WorldPackets::SendCreateCharacter(packet->systemAddress, player->GetComponent<CharacterComponent>()->GetReputation(), player->GetObjectID(), c->GetXMLData(), username, c->GetGMLevel(), c->GetPropertyCloneID());
WorldPackets::SendServerState(packet->systemAddress);
const auto respawnPoint = player->GetCharacter()->GetRespawnPoint(Game::zoneManager->GetZone()->GetWorldID());
Game::entityManager->ConstructEntity(player, UNASSIGNED_SYSTEM_ADDRESS);
if (respawnPoint != NiPoint3Constant::ZERO) {
GameMessages::SendPlayerReachedRespawnCheckpoint(player, respawnPoint, QuatUtils::IDENTITY);
}
Game::entityManager->ConstructAllEntities(packet->systemAddress);
characterComponent->RocketUnEquip(player);
// Do charxml fixes here
auto* levelComponent = player->GetComponent<LevelProgressionComponent>();
auto* const inventoryComponent = player->GetComponent<InventoryComponent>();
@@ -1060,6 +1046,7 @@ void HandlePacket(Packet* packet) {
if (!levelComponent || !missionComponent || !inventoryComponent) return;
auto version = levelComponent->GetCharacterVersion();
LOG("Updating character from version %s", StringifiedEnum::ToString(version).data());
switch (version) {
case eCharacterVersion::RELEASE:
// TODO: Implement, super low priority
@@ -1108,6 +1095,29 @@ void HandlePacket(Packet* packet) {
}
if (complete) missionComponent->CompleteMission(937 /* Nexus Force explorer */);
levelComponent->SetCharacterVersion(eCharacterVersion::NEXUS_FORCE_EXPLORER);
[[fallthrough]];
}
case eCharacterVersion::NEXUS_FORCE_EXPLORER: {
LOG("Fixing pet IDs");
// First copy the original ids
const auto pets = inventoryComponent->GetPetsMut();
// Then clear the pets so we can re-add them with the updated IDs
auto& invPets = inventoryComponent->GetPetsMut();
invPets.clear();
for (auto& [id, databasePet] : pets) {
const auto originalID = id;
const auto newId = GeneralUtils::ClearBit(id, 32); // Persistent bit that didn't exist
LOG("New ID %llu", newId);
auto* item = inventoryComponent->FindItemBySubKey(originalID);
if (item) {
LOG("item subkey %llu", item->GetSubKey());
item->SetSubKey(newId);
invPets[newId] = databasePet;
}
}
levelComponent->SetCharacterVersion(eCharacterVersion::UP_TO_DATE);
[[fallthrough]];
}
@@ -1115,6 +1125,24 @@ void HandlePacket(Packet* packet) {
break;
}
// Update the characters xml to ensure the update above is not only saved, but so the client picks up on the changes.
c->SaveXMLToDatabase();
WorldPackets::SendCreateCharacter(packet->systemAddress, characterComponent->GetReputation(), player->GetObjectID(), c->GetXMLData(), username, c->GetGMLevel(), c->GetPropertyCloneID());
WorldPackets::SendServerState(packet->systemAddress);
const auto respawnPoint = player->GetCharacter()->GetRespawnPoint(Game::zoneManager->GetZone()->GetWorldID());
Game::entityManager->ConstructEntity(player, UNASSIGNED_SYSTEM_ADDRESS);
if (respawnPoint != NiPoint3Constant::ZERO) {
GameMessages::SendPlayerReachedRespawnCheckpoint(player, respawnPoint, QuatUtils::IDENTITY);
}
Game::entityManager->ConstructAllEntities(packet->systemAddress);
characterComponent->RocketUnEquip(player);
player->GetCharacter()->SetTargetScene("");
// Fix the destroyable component
@@ -1149,8 +1177,6 @@ void HandlePacket(Packet* packet) {
//Send message:
LWOOBJID blueprintID = bbbModel.id;
GeneralUtils::SetBit(blueprintID, eObjectBits::CHARACTER);
GeneralUtils::SetBit(blueprintID, eObjectBits::PERSISTENT);
// Workaround for not having a UGC server to get model LXFML onto the client so it
// can generate the physics and nif for the object.