1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-05-23 02:07:45 +00:00
sapphire/src/common/Util/SpawnIndexAllocator.h
AriAvery 8dd40b1378 Cleanup, Improvements
- Refactored datReader and several other files for code cleanliness
- Enhanced runtime performance by optimizing select functions, utilizing std::string_view in place of std::string where appropriate
- Removed deprecated filesystem implementation
- Introduced Link Time Optimization (LTO) support for Linux builds
- Enabled parallel builds for GCC/Clang compilers
- Expanded and improved comments for various functions
- Replaced version check failure with warning, allowing for continued use with a cautionary message

Tested on MSVC/Windows and Clang/Ubuntu
2023-04-26 13:58:41 +02:00

124 lines
No EOL
3.8 KiB
C++

#pragma once
#include <type_traits>
#include <unordered_set>
namespace Sapphire::Common::Util
{
// The SpawnIndexAllocator class template is a utility class that allocates
// unique indices for spawned objects in the game world. It is parameterized
// by the index type T and an optional actor ID type.
template< typename T, typename ActorIdType = uint32_t >
class SpawnIndexAllocator
{
public:
static_assert( std::is_same< T, uint8_t >::value || std::is_same< T, uint16_t >::value ||
std::is_same< T, uint32_t >::value || std::is_same< T, uint64_t >::value,
"T must be uint8_t, uint16_t, uint32_t, uint64_t" );
// Constructor for the SpawnIndexAllocator, initializing internal variables
// such as maximum slot ID, reserve first slot flag, and allocation failure ID.
SpawnIndexAllocator() : m_maxSlotId( 0 ),
m_reserveFirstSlot( false ),
m_allocFailId( static_cast< T >( -1 ) )
{
}
// Initializes the SpawnIndexAllocator by setting the maximum slot ID and
// whether to reserve the first slot. Sets up the free and used index sets.
void init( T maxSlotId, bool reserveFirstSlot = false )
{
m_maxSlotId = maxSlotId;
m_reserveFirstSlot = reserveFirstSlot;
setupSet();
// reserve max slot id in set to prevent any runtime rehashing
m_freeIndexes.reserve( m_maxSlotId );
m_usedIndexes.reserve( m_maxSlotId );
}
// Frees a used spawn index, given an actor ID. Removes the index from the
// used set and adds it back to the free set. Returns the freed index or
// the allocation failure ID if the actor ID is not found.
T freeUsedSpawnIndex( ActorIdType actorId )
{
auto it = m_usedIndexes.find( actorId );
if( it == m_usedIndexes.end() )
return m_allocFailId;
auto index = *it;
m_usedIndexes.erase( it );
m_freeIndexes.insert( index );
return index;
}
// Allocates the next free spawn index and associates it with the given
// actor ID. Removes the index from the free set and adds it to the used set.
// Returns the allocated index or the allocation failure ID if there are no
// free indices.
T getNextFreeSpawnIndex( ActorIdType actorId )
{
assert( m_maxSlotId != 0 );
if( m_freeIndexes.empty() )
return m_allocFailId;
auto nextId = *m_freeIndexes.begin();
m_freeIndexes.erase( m_freeIndexes.begin() );
m_usedIndexes.insert( nextId );
return nextId;
}
// Frees all used spawn indices and clears the used set. Resets the free
// set to contain all possible indices.
void freeAllSpawnIndexes()
{
setupSet();
m_usedIndexes.clear();
}
// Returns true if the given spawn index is valid (i.e., not equal to the
// allocation failure ID), false otherwise.
bool isSpawnIndexValid( T spawnIndex )
{
return spawnIndex != m_allocFailId;
}
// Returns the allocation failure ID.
constexpr T getAllocFailId() const
{
return m_allocFailId;
}
protected:
// Sets up the free index set by inserting all possible spawn indices
// into the set, optionally reserving the first slot.
void setupSet()
{
assert( m_maxSlotId != 0 );
m_freeIndexes.clear();
uint32_t start = 0;
// slot is reserved when used for spawning actors/players otherwise the local player actor spawnIndex
// will be used by another actor and despawn the local player
if( m_reserveFirstSlot )
start = 1;
for( uint32_t i = start; i < m_maxSlotId; i++ )
m_freeIndexes.insert( i );
}
std::unordered_set< T > m_freeIndexes;
std::unordered_set< T > m_usedIndexes;
T m_maxSlotId;
bool m_reserveFirstSlot;
const T m_allocFailId;
};
}// namespace Sapphire::Common::Util