Skip to content

Commit

Permalink
Merge pull request #6449 from LandSandBoat/widescantarget
Browse files Browse the repository at this point in the history
Core: Replace entity ptr for WideScanTarget with EntityID_t
  • Loading branch information
zach2good authored Nov 21, 2024
2 parents f81df2a + aa8d740 commit 13d5c31
Show file tree
Hide file tree
Showing 11 changed files with 193 additions and 27 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,7 @@
"__config": "cpp",
"__hash_table": "cpp",
"__node_handle": "cpp",
"__verbose_abort": "cpp"
"__verbose_abort": "cpp",
"__locale": "cpp"
},
}
6 changes: 2 additions & 4 deletions src/common/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
===========================================================================
*/

#ifndef _UTILS_H_
#define _UTILS_H_
#pragma once

#define _USE_MATH_DEFINES

#include "common/cbasetypes.h"
Expand Down Expand Up @@ -146,5 +146,3 @@ static mutex_guarded<std::unordered_map<std::string, time_point>> lastExecutionT
}); \
}
// clang-format on

#endif
142 changes: 142 additions & 0 deletions src/common/xi.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/*
===========================================================================
Copyright (c) 2024 LandSandBoat Dev Teams
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/
===========================================================================
*/

#pragma once

#include <optional>
#include <type_traits>
#include <utility>

// The purpose of this namespace IS NOT to replace the C++ standard library.
//
// It is to provide convenience wrappers around common standard library types
// so that they are easier and more intuitive to use in the context of this project.
//
// You should be:
// - Forwarding all of the expected and useful functions from the underlying standard library type
// - Not forwarding/hiding the ones that are not useful
// - Adding new functions that are useful and convenient

namespace xi
{

// A wrapper around std::optional to allow usage of object.apply([](auto& obj) { ... });
// https://en.cppreference.com/w/cpp/utility/optional
template <typename T>
class optional
{
public:
constexpr optional() = default;
constexpr explicit optional(std::nullopt_t) noexcept
: m_value(std::nullopt)
{
}
constexpr optional(const optional& other) = default;
constexpr optional(optional&& other) noexcept = default;
constexpr optional& operator=(const optional& other) = default;
constexpr optional& operator=(optional&& other) noexcept = default;
~optional() = default;

constexpr optional& operator=(std::nullopt_t) noexcept
{
m_value = std::nullopt;
return *this;
}

constexpr optional& operator=(T&& value)
{
m_value = std::move(value);
return *this;
}

template <typename F>
constexpr void apply(F&& f) &
{
if (m_value)
{
f(*m_value);
}
}

template <typename F>
constexpr void apply(F&& f) const&
{
if (m_value)
{
f(*m_value);
}
}

constexpr explicit operator bool() const noexcept
{
return m_value.has_value();
}

constexpr T& operator*() &
{
return *m_value;
}

constexpr const T& operator*() const&
{
return *m_value;
}

constexpr T* operator->() noexcept
{
return m_value.operator->();
}

constexpr const T* operator->() const noexcept
{
return m_value.operator->();
}

constexpr void reset() noexcept
{
m_value.reset();
}

template <typename... Args>
constexpr T& emplace(Args&&... args)
{
return m_value.emplace(std::forward<Args>(args)...);
}

constexpr bool operator==(const optional& other) const
{
return m_value == other.m_value;
}

constexpr bool operator!=(const optional& other) const
{
return m_value != other.m_value;
}

private:
std::optional<T> m_value;
};

// TODO: A wrapper around std::variant to allow usage of:
// : object.visit(overloaded{...});
// : object.get<T>() -> xi::optional<T>;

} // namespace xi
14 changes: 10 additions & 4 deletions src/map/entities/baseentity.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,18 +206,24 @@ enum class SPAWN_ANIMATION : uint8
SPECIAL = 1,
};

// TODO:it is possible to make this structure part of the class, instead of the current ID and Targid, but without the Clean method

// TODO: It is possible to make this structure part of the class, instead of the current ID and Targid, but without the clean() method.
struct EntityID_t
{
// TODO: Add a constructor that takes an id and targid.
// TODO: Clean with a destructor.
void clean()
{
id = 0;
targid = 0;
}

uint32 id;
uint16 targid;
// TODO: Globally rename targid to index, zoneIndex, etc.

uint32 id; // "Long" global ID of the entity. Built from 0x10000000 | (zoneId << 16) | targid.
uint16 targid; // The "index" of the entity in the current zone. Used for local targeting and referencing.

// TODO: Store the zoneId of this entity's zone. We can then use the targid (index) and the zoneId to build the global id.
// TODO: Store an incremental u64 as a UUID for the entity for disambiguation in the case of dynamic entities that might have the same targid.
};

class CAIContainer;
Expand Down
11 changes: 6 additions & 5 deletions src/map/entities/charentity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,15 +209,16 @@ CCharEntity::CCharEntity()

BazaarID.clean();

WideScanTarget = std::nullopt;

lastTradeInvite = {};
TradePending.clean();
InvitePending.clean();

PLinkshell1 = nullptr;
PLinkshell2 = nullptr;
PUnityChat = nullptr;
PTreasurePool = nullptr;
PWideScanTarget = nullptr;
PLinkshell1 = nullptr;
PLinkshell2 = nullptr;
PUnityChat = nullptr;
PTreasurePool = nullptr;

PAutomaton = nullptr;
PClaimedMob = nullptr;
Expand Down
7 changes: 6 additions & 1 deletion src/map/entities/charentity.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

#include "common/cbasetypes.h"
#include "common/mmo.h"
#include "common/xi.h"

#include <bitset>
#include <deque>
Expand Down Expand Up @@ -444,7 +445,11 @@ class CCharEntity : public CBattleEntity
CUContainer* UContainer; // Container used for universal actions -- used for trading at least despite the dedicated trading container above
CTradeContainer* CraftContainer; // Container used for crafting actions.

CBaseEntity* PWideScanTarget;
// TODO: All member instances of EntityID_t should be std::optional<EntityID_t> to allow for them not to be set,
// : instead of checking for entityId.id != 0, etc.
// TODO: We don't want to replace this with just an ID, because in the future EntityID_t will be able to
// : disambiguate between entities who have been rebuilt (players, dynamic entities) and have the same ID.
xi::optional<EntityID_t> WideScanTarget;

SpawnIDList_t SpawnPCList; // list of visible characters
SpawnIDList_t SpawnMOBList; // list of visible monsters
Expand Down
28 changes: 20 additions & 8 deletions src/map/packet_system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -592,15 +592,24 @@ void SmallPacket0x015(map_session_data_t* const PSession, CCharEntity* const PCh
PChar->loc.zone->SpawnTRUSTs(PChar);
PChar->requestedInfoSync = true; // Ask to update PCs during CZoneEntities::ZoneServer

if (PChar->PWideScanTarget != nullptr)
// clang-format off
PChar->WideScanTarget.apply([&](const auto& wideScanTarget)
{
PChar->pushPacket(new CWideScanTrackPacket(PChar->PWideScanTarget));
if (const auto* PWideScanEntity = PChar->GetEntity(wideScanTarget.targid, TYPE_MOB | TYPE_NPC))
{
PChar->pushPacket(new CWideScanTrackPacket(PWideScanEntity));

if (PChar->PWideScanTarget->status == STATUS_TYPE::DISAPPEAR)
if (PWideScanEntity->status == STATUS_TYPE::DISAPPEAR)
{
PChar->WideScanTarget = std::nullopt;
}
}
else
{
PChar->PWideScanTarget = nullptr;
PChar->WideScanTarget = std::nullopt;
}
}
});
// clang-format on
}
}

Expand Down Expand Up @@ -6910,7 +6919,7 @@ void SmallPacket0x0F5(map_session_data_t* const PSession, CCharEntity* const PCh
if (target == nullptr)
{
// Target not found
PChar->PWideScanTarget = nullptr;
PChar->WideScanTarget = std::nullopt;
return;
}

Expand All @@ -6920,7 +6929,10 @@ void SmallPacket0x0F5(map_session_data_t* const PSession, CCharEntity* const PCh
// Only allow players to track targets that are actually scannable, and within their wide scan range
if (target->isWideScannable() && dist <= widescanRange)
{
PChar->PWideScanTarget = target;
PChar->WideScanTarget = EntityID_t{
.id = target->id,
.targid = target->targid
};
}
}

Expand All @@ -6933,7 +6945,7 @@ void SmallPacket0x0F5(map_session_data_t* const PSession, CCharEntity* const PCh
void SmallPacket0x0F6(map_session_data_t* const PSession, CCharEntity* const PChar, CBasicPacket& data)
{
TracyZoneScoped;
PChar->PWideScanTarget = nullptr;
PChar->WideScanTarget = std::nullopt;
}

/************************************************************************
Expand Down
2 changes: 1 addition & 1 deletion src/map/packets/wide_scan_track.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
#include "entities/baseentity.h"
#include "wide_scan_track.h"

CWideScanTrackPacket::CWideScanTrackPacket(CBaseEntity* PEntity)
CWideScanTrackPacket::CWideScanTrackPacket(const CBaseEntity* PEntity)
{
this->setType(0xF5);
this->setSize(0x18);
Expand Down
2 changes: 1 addition & 1 deletion src/map/packets/wide_scan_track.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class CBaseEntity;
class CWideScanTrackPacket : public CBasicPacket
{
public:
CWideScanTrackPacket(CBaseEntity* PEntity);
CWideScanTrackPacket(const CBaseEntity* PEntity);
};

#endif
3 changes: 2 additions & 1 deletion src/map/utils/charutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7184,7 +7184,8 @@ namespace charutils

PChar->TradePending.clean();
PChar->InvitePending.clean();
PChar->PWideScanTarget = nullptr;

PChar->WideScanTarget = std::nullopt;

if (PChar->animation == ANIMATION_ATTACK)
{
Expand Down
2 changes: 1 addition & 1 deletion src/map/utils/itemutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,7 @@ namespace itemutils

/************************************************************************
* *
* Initialization of the game objects bbbb *
* Initialization of the game objects *
* *
************************************************************************/

Expand Down

0 comments on commit 13d5c31

Please sign in to comment.