Skip to content

Commit

Permalink
Merge pull request #1675 from DarkflameUniverse/invisible-items
Browse files Browse the repository at this point in the history
the client code for this is a mess and should load everything at once or use non race condition code
  • Loading branch information
aronwk-aaron authored Dec 11, 2024
2 parents 02b76ad + 3beb414 commit 3461860
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 4 deletions.
19 changes: 19 additions & 0 deletions dGame/dComponents/InventoryComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1141,6 +1141,25 @@ void InventoryComponent::AddItemSkills(const LOT lot) {
SetSkill(slot, skill);
}

void InventoryComponent::FixInvisibleItems() {
const auto numberItemsLoadedPerFrame = 12.0f;
const auto callbackTime = 0.125f;
const auto arbitaryInventorySize = 300.0f; // max in live + dlu is less than 300, seems like a good number.
auto* const items = GetInventory(eInventoryType::ITEMS);
if (!items) return;

// Add an extra update to make sure the client can see all the items.
const auto something = static_cast<int32_t>(std::ceil(items->GetItems().size() / arbitaryInventorySize)) + 1;
LOG_DEBUG("Fixing invisible items with %i updates", something);

for (int32_t i = 1; i < something + 1; i++) {
// client loads 12 items every 1/8 seconds, we're adding a small hack to fix invisible inventory items due to closing the news screen too fast.
m_Parent->AddCallbackTimer((arbitaryInventorySize / numberItemsLoadedPerFrame) * callbackTime * i, [this]() {
GameMessages::SendUpdateInventoryUi(m_Parent->GetObjectID(), m_Parent->GetSystemAddress());
});
}
}

void InventoryComponent::RemoveItemSkills(const LOT lot) {
const auto info = Inventory::FindItemComponent(lot);

Expand Down
2 changes: 2 additions & 0 deletions dGame/dComponents/InventoryComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,8 @@ class InventoryComponent final : public Component {
void UpdateGroup(const GroupUpdate& groupUpdate);
void RemoveGroup(const std::string& groupId);

void FixInvisibleItems();

~InventoryComponent() override;

private:
Expand Down
12 changes: 12 additions & 0 deletions dGame/dGameMessages/GameMessageHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,18 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream& inStream, const System
break;
}

// Currently not actually used for our implementation, however its used right now to get around invisible inventory items in the client.
case MessageType::Game::SELECT_SKILL: {
auto var = entity->GetVar<bool>(u"dlu_first_time_load");
if (var) {
entity->SetVar<bool>(u"dlu_first_time_load", false);
InventoryComponent* inventoryComponent = entity->GetComponent<InventoryComponent>();

if (inventoryComponent) inventoryComponent->FixInvisibleItems();
}
break;
}

case MessageType::Game::PLAYER_LOADED: {
GameMessages::SendRestoreToPostLoadStats(entity, sysAddr);
entity->SetPlayerReadyForUpdates();
Expand Down
25 changes: 21 additions & 4 deletions dGame/dGameMessages/GameMessages.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -982,7 +982,7 @@ void GameMessages::SendResurrect(Entity* entity) {
destroyableComponent->SetImagination(imaginationToRestore);
}
}
});
});

CBITSTREAM;
CMSGHEADER;
Expand Down Expand Up @@ -5080,6 +5080,12 @@ void GameMessages::HandleSetFlag(RakNet::BitStream& inStream, Entity* entity) {

auto character = entity->GetCharacter();
if (character) character->SetPlayerFlag(iFlagID, bFlag);

// This is always set the first time a player loads into a world from character select
// and is used to know when to refresh the players inventory items so they show up.
if (iFlagID == ePlayerFlag::IS_NEWS_SCREEN_VISIBLE && bFlag) {
entity->SetVar<bool>(u"dlu_first_time_load", true);
}
}

void GameMessages::HandleRespondToMission(RakNet::BitStream& inStream, Entity* entity) {
Expand Down Expand Up @@ -5147,12 +5153,12 @@ void GameMessages::HandleMissionDialogOK(RakNet::BitStream& inStream, Entity* en
}

if (Game::config->GetValue("allow_players_to_skip_cinematics") != "1"
|| !player->GetCharacter()
|| !player->GetCharacter()->GetPlayerFlag(ePlayerFlag::DLU_SKIP_CINEMATICS)) return;
|| !player->GetCharacter()
|| !player->GetCharacter()->GetPlayerFlag(ePlayerFlag::DLU_SKIP_CINEMATICS)) return;
player->AddCallbackTimer(0.5f, [player]() {
if (!player) return;
GameMessages::SendEndCinematic(player->GetObjectID(), u"", player->GetSystemAddress());
});
});
}

void GameMessages::HandleRequestLinkedMission(RakNet::BitStream& inStream, Entity* entity) {
Expand Down Expand Up @@ -6324,3 +6330,14 @@ void GameMessages::SendForceCameraTargetCycle(Entity* entity, bool bForceCycling
auto sysAddr = entity->GetSystemAddress();
SEND_PACKET;
}


void GameMessages::SendUpdateInventoryUi(LWOOBJID objectId, const SystemAddress& sysAddr) {
CBITSTREAM;
CMSGHEADER;

bitStream.Write(objectId);
bitStream.Write(MessageType::Game::UPDATE_INVENTORY_UI);

SEND_PACKET;
}
3 changes: 3 additions & 0 deletions dGame/dGameMessages/GameMessages.h
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,9 @@ namespace GameMessages {
void HandleUpdateInventoryGroup(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr);
void HandleUpdateInventoryGroupContents(RakNet::BitStream& inStream, Entity* entity, const SystemAddress& sysAddr);
void SendForceCameraTargetCycle(Entity* entity, bool bForceCycling, eCameraTargetCyclingMode cyclingMode, LWOOBJID optionalTargetID);

// This is a client gm however its default values are exactly what we need to get around the invisible inventory item issues.
void SendUpdateInventoryUi(LWOOBJID objectId, const SystemAddress& sysAddr);
};

#endif // GAMEMESSAGES_H

0 comments on commit 3461860

Please sign in to comment.