v1.4.4
This commit is contained in:
commit
9c94d113d3
10260 changed files with 1237388 additions and 0 deletions
189
source/game/StarEntityMap.hpp
Normal file
189
source/game/StarEntityMap.hpp
Normal file
|
@ -0,0 +1,189 @@
|
|||
#ifndef STAR_ENTITY_MAP_HPP
|
||||
#define STAR_ENTITY_MAP_HPP
|
||||
|
||||
#include "StarSpatialHash2D.hpp"
|
||||
#include "StarEntity.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
STAR_CLASS(EntityMap);
|
||||
STAR_CLASS(TileEntity);
|
||||
STAR_CLASS(InteractiveEntity);
|
||||
|
||||
STAR_EXCEPTION(EntityMapException, StarException);
|
||||
|
||||
// Class used by WorldServer and WorldClient to store entites organized in a
|
||||
// spatial hash. Provides convenient ways of querying entities based on
|
||||
// different selection criteria.
|
||||
//
|
||||
// Several of the methods in EntityMap take callbacks or filters that will be
|
||||
// called while iterating over internal structures. They are all designed so
|
||||
// that adding new entities is safe to do from the callback, but removing
|
||||
// entities is never safe to do from any callback function.
|
||||
class EntityMap {
|
||||
public:
|
||||
static float const SpatialHashSectorSize;
|
||||
static int const MaximumEntityBoundBox;
|
||||
|
||||
// beginIdSpace and endIdSpace is the *inclusive* range for new enittyIds.
|
||||
EntityMap(Vec2U const& worldSize, EntityId beginIdSpace, EntityId endIdSpace);
|
||||
|
||||
// Get the next free id in the entity id space.
|
||||
EntityId reserveEntityId();
|
||||
|
||||
// Add an entity to this EntityMap. The entity must already be initialized
|
||||
// and have a unique EntityId returned by reserveEntityId.
|
||||
void addEntity(EntityPtr entity);
|
||||
EntityPtr removeEntity(EntityId entityId);
|
||||
|
||||
size_t size() const;
|
||||
List<EntityId> entityIds() const;
|
||||
|
||||
// Iterates through the entity map optionally in the given order, updating
|
||||
// the spatial information for each entity along the way.
|
||||
void updateAllEntities(EntityCallback const& callback = {}, function<bool(EntityPtr const&, EntityPtr const&)> sortOrder = {});
|
||||
|
||||
// If the given unique entity is in this map, then return its entity id
|
||||
EntityId uniqueEntityId(String const& uniqueId) const;
|
||||
|
||||
EntityPtr entity(EntityId entityId) const;
|
||||
EntityPtr uniqueEntity(String const& uniqueId) const;
|
||||
|
||||
// Queries entities based on metaBoundBox
|
||||
List<EntityPtr> entityQuery(RectF const& boundBox, EntityFilter const& filter = {}) const;
|
||||
|
||||
// A fuzzy query of the entities at this position, sorted by closeness.
|
||||
List<EntityPtr> entitiesAt(Vec2F const& pos, EntityFilter const& filter = {}) const;
|
||||
|
||||
List<TileEntityPtr> entitiesAtTile(Vec2I const& pos, EntityFilterOf<TileEntity> const& filter = {}) const;
|
||||
|
||||
// Sort of a fuzzy line intersection test. Tests if a given line intersects
|
||||
// the bounding box of any entities, and returns them.
|
||||
List<EntityPtr> entityLineQuery(Vec2F const& begin, Vec2F const& end, EntityFilter const& filter = {}) const;
|
||||
|
||||
// Callback versions of query functions.
|
||||
void forEachEntity(RectF const& boundBox, EntityCallback const& callback) const;
|
||||
void forEachEntityLine(Vec2F const& begin, Vec2F const& end, EntityCallback const& callback) const;
|
||||
// Returns tile-based entities that occupy the given tile position.
|
||||
void forEachEntityAtTile(Vec2I const& pos, EntityCallbackOf<TileEntity> const& callback) const;
|
||||
|
||||
// Iterate through all the entities, optionally in the given sort order.
|
||||
void forAllEntities(EntityCallback const& callback, function<bool(EntityPtr const&, EntityPtr const&)> sortOrder = {}) const;
|
||||
|
||||
// Stops searching when filter returns true, and returns the entity which
|
||||
// caused it.
|
||||
EntityPtr findEntity(RectF const& boundBox, EntityFilter const& filter) const;
|
||||
EntityPtr findEntityLine(Vec2F const& begin, Vec2F const& end, EntityFilter const& filter) const;
|
||||
EntityPtr findEntityAtTile(Vec2I const& pos, EntityFilterOf<TileEntity> const& filter) const;
|
||||
|
||||
// Closest entity that satisfies the given selector, if given.
|
||||
EntityPtr closestEntity(Vec2F const& center, float radius, EntityFilter const& filter = {}) const;
|
||||
|
||||
// Returns interactive entity that is near the given world position
|
||||
InteractiveEntityPtr interactiveEntityNear(Vec2F const& pos, float maxRadius = 1.5f) const;
|
||||
|
||||
// Whether or not any tile entity occupies this tile
|
||||
bool tileIsOccupied(Vec2I const& pos, bool includeEphemeral = false) const;
|
||||
|
||||
// Intersects any entity's collision area
|
||||
bool spaceIsOccupied(RectF const& rect, bool includeEphemeral = false) const;
|
||||
|
||||
// Convenience template methods that filter based on dynamic cast and deal
|
||||
// with pointers to a derived entity type.
|
||||
|
||||
template <typename EntityT>
|
||||
shared_ptr<EntityT> get(EntityId entityId) const;
|
||||
|
||||
template <typename EntityT>
|
||||
shared_ptr<EntityT> getUnique(String const& uniqueId) const;
|
||||
|
||||
template <typename EntityT>
|
||||
List<shared_ptr<EntityT>> query(RectF const& boundBox, EntityFilterOf<EntityT> const& filter = {}) const;
|
||||
|
||||
template <typename EntityT>
|
||||
List<shared_ptr<EntityT>> all(EntityFilterOf<EntityT> const& filter = {}) const;
|
||||
|
||||
template <typename EntityT>
|
||||
List<shared_ptr<EntityT>> lineQuery(Vec2F const& begin, Vec2F const& end, EntityFilterOf<EntityT> const& filter = {}) const;
|
||||
|
||||
template <typename EntityT>
|
||||
shared_ptr<EntityT> closest(Vec2F const& center, float radius, EntityFilterOf<EntityT> const& filter = {}) const;
|
||||
|
||||
template <typename EntityT>
|
||||
List<shared_ptr<EntityT>> atTile(Vec2I const& pos) const;
|
||||
|
||||
private:
|
||||
typedef SpatialHash2D<EntityId, float, EntityPtr> SpatialMap;
|
||||
|
||||
WorldGeometry m_geometry;
|
||||
|
||||
SpatialMap m_spatialMap;
|
||||
BiHashMap<String, EntityId> m_uniqueMap;
|
||||
|
||||
EntityId m_nextId;
|
||||
EntityId m_beginIdSpace;
|
||||
EntityId m_endIdSpace;
|
||||
|
||||
List<SpatialMap::Entry const*> m_entrySortBuffer;
|
||||
};
|
||||
|
||||
template <typename EntityT>
|
||||
shared_ptr<EntityT> EntityMap::get(EntityId entityId) const {
|
||||
return as<EntityT>(entity(entityId));
|
||||
}
|
||||
|
||||
template <typename EntityT>
|
||||
shared_ptr<EntityT> EntityMap::getUnique(String const& uniqueId) const {
|
||||
return as<EntityT>(uniqueEntity(uniqueId));
|
||||
}
|
||||
|
||||
template <typename EntityT>
|
||||
List<shared_ptr<EntityT>> EntityMap::query(RectF const& boundBox, EntityFilterOf<EntityT> const& filter) const {
|
||||
List<shared_ptr<EntityT>> entities;
|
||||
for (auto const& entity : entityQuery(boundBox, entityTypeFilter(filter)))
|
||||
entities.append(as<EntityT>(entity));
|
||||
|
||||
return entities;
|
||||
}
|
||||
|
||||
template <typename EntityT>
|
||||
List<shared_ptr<EntityT>> EntityMap::all(EntityFilterOf<EntityT> const& filter) const {
|
||||
List<shared_ptr<EntityT>> entities;
|
||||
forAllEntities([&](EntityPtr const& entity) {
|
||||
if (auto e = as<EntityT>(entity)) {
|
||||
if (!filter || filter(e))
|
||||
entities.append(e);
|
||||
}
|
||||
});
|
||||
|
||||
return entities;
|
||||
}
|
||||
|
||||
template <typename EntityT>
|
||||
List<shared_ptr<EntityT>> EntityMap::lineQuery(Vec2F const& begin, Vec2F const& end, EntityFilterOf<EntityT> const& filter) const {
|
||||
List<shared_ptr<EntityT>> entities;
|
||||
for (auto const& entity : entityLineQuery(begin, end, entityTypeFilter(filter)))
|
||||
entities.append(as<EntityT>(entity));
|
||||
|
||||
return entities;
|
||||
}
|
||||
|
||||
template <typename EntityT>
|
||||
shared_ptr<EntityT> EntityMap::closest(Vec2F const& center, float radius, EntityFilterOf<EntityT> const& filter) const {
|
||||
return as<EntityT>(closestEntity(center, radius, entityTypeFilter(filter)));
|
||||
}
|
||||
|
||||
template <typename EntityT>
|
||||
List<shared_ptr<EntityT>> EntityMap::atTile(Vec2I const& pos) const {
|
||||
List<shared_ptr<EntityT>> list;
|
||||
forEachEntityAtTile(pos, [&](TileEntityPtr const& entity) {
|
||||
if (auto e = as<EntityT>(entity))
|
||||
list.append(move(e));
|
||||
return false;
|
||||
});
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue