431a9c00a5
On Linux and macOS, using Clang to compile OpenStarbound produces about 400 MB worth of warnings during the build, making the compiler output unreadable and slowing the build down considerably. 99% of the warnings were unqualified uses of std::move and std::forward, which are now all properly qualified. Fixed a few other minor warnings about non-virtual destructors and some uses of std::move preventing copy elision on temporary objects. Most remaining warnings are now unused parameters.
263 lines
12 KiB
C++
263 lines
12 KiB
C++
#ifndef STAR_WORLD_HPP
|
|
#define STAR_WORLD_HPP
|
|
|
|
#include "StarTileEntity.hpp"
|
|
#include "StarInteractionTypes.hpp"
|
|
#include "StarCollisionBlock.hpp"
|
|
#include "StarForceRegions.hpp"
|
|
#include "StarWorldGeometry.hpp"
|
|
#include "StarTileModification.hpp"
|
|
#include "StarLuaRoot.hpp"
|
|
#include "StarRpcPromise.hpp"
|
|
|
|
namespace Star {
|
|
|
|
STAR_CLASS(World);
|
|
STAR_CLASS(TileEntity);
|
|
STAR_CLASS(ScriptedEntity);
|
|
|
|
typedef function<void(World*)> WorldAction;
|
|
|
|
class World {
|
|
public:
|
|
virtual ~World() {}
|
|
|
|
// Will remain constant throughout the life of the world.
|
|
virtual ConnectionId connection() const = 0;
|
|
virtual WorldGeometry geometry() const = 0;
|
|
|
|
// Update frame counter. Returns the frame that is *currently* being
|
|
// updated, not the *last* frame, so during the first call to update(), this
|
|
// would return 1
|
|
virtual uint64_t currentStep() const = 0;
|
|
|
|
// All methods that take int parameters wrap around or clamp so that all int
|
|
// values are valid world indexes.
|
|
|
|
virtual MaterialId material(Vec2I const& position, TileLayer layer) const = 0;
|
|
virtual MaterialHue materialHueShift(Vec2I const& position, TileLayer layer) const = 0;
|
|
virtual ModId mod(Vec2I const& position, TileLayer layer) const = 0;
|
|
virtual MaterialHue modHueShift(Vec2I const& position, TileLayer layer) const = 0;
|
|
virtual MaterialColorVariant colorVariant(Vec2I const& position, TileLayer layer) const = 0;
|
|
virtual LiquidLevel liquidLevel(Vec2I const& pos) const = 0;
|
|
virtual LiquidLevel liquidLevel(RectF const& region) const = 0;
|
|
|
|
// Tests a tile modification list and returns the ones that are valid.
|
|
virtual TileModificationList validTileModifications(TileModificationList const& modificationList, bool allowEntityOverlap) const = 0;
|
|
// Apply a list of tile modifications in the best order to apply as many
|
|
// possible, and returns the modifications that could not be applied.
|
|
virtual TileModificationList applyTileModifications(TileModificationList const& modificationList, bool allowEntityOverlap) = 0;
|
|
|
|
virtual bool isTileProtected(Vec2I const& pos) const = 0;
|
|
|
|
virtual EntityPtr entity(EntityId entityId) const = 0;
|
|
// *If* the entity is initialized immediately and locally, then will use the
|
|
// passed in pointer directly and initialize it, and entity will have a valid
|
|
// id in this world and be ready for use. This is always the case on the
|
|
// server, but not *always* the case on the client.
|
|
virtual void addEntity(EntityPtr const& entity, EntityId entityId = NullEntityId) = 0;
|
|
|
|
virtual EntityPtr closestEntity(Vec2F const& center, float radius, EntityFilter selector = {}) const = 0;
|
|
|
|
virtual void forAllEntities(EntityCallback entityCallback) const = 0;
|
|
|
|
// Query here is a fuzzy query based on metaBoundBox
|
|
virtual void forEachEntity(RectF const& boundBox, EntityCallback entityCallback) const = 0;
|
|
// Fuzzy metaBoundBox query for intersecting the given line.
|
|
virtual void forEachEntityLine(Vec2F const& begin, Vec2F const& end, EntityCallback entityCallback) const = 0;
|
|
// Performs action for all entities that occupies the given tile position
|
|
// (only entity types laid out in the tile grid).
|
|
virtual void forEachEntityAtTile(Vec2I const& pos, EntityCallbackOf<TileEntity> entityCallback) const = 0;
|
|
|
|
// Like forEachEntity, but stops scanning when entityFilter returns true, and
|
|
// returns the EntityPtr found, otherwise returns a null pointer.
|
|
virtual EntityPtr findEntity(RectF const& boundBox, EntityFilter entityFilter) const = 0;
|
|
virtual EntityPtr findEntityLine(Vec2F const& begin, Vec2F const& end, EntityFilter entityFilter) const = 0;
|
|
virtual EntityPtr findEntityAtTile(Vec2I const& pos, EntityFilterOf<TileEntity> entityFilter) const = 0;
|
|
|
|
// Is the given tile layer and position occupied by an entity or block?
|
|
virtual bool tileIsOccupied(Vec2I const& pos, TileLayer layer, bool includeEphemeral = false, bool checkCollision = false) const = 0;
|
|
|
|
// Returns the collision kind of a tile.
|
|
virtual CollisionKind tileCollisionKind(Vec2I const& pos) const = 0;
|
|
|
|
// Iterate over the collision block for each tile in the region. Collision
|
|
// polys for tiles can extend to a maximum of 1 tile outside of the natural
|
|
// tile bounds.
|
|
virtual void forEachCollisionBlock(RectI const& region, function<void(CollisionBlock const&)> const& iterator) const = 0;
|
|
|
|
// Is there some connectable tile / tile based entity in this position? If
|
|
// tilesOnly is true, only checks to see whether that tile is a connectable
|
|
// material.
|
|
virtual bool isTileConnectable(Vec2I const& pos, TileLayer layer, bool tilesOnly = false) const = 0;
|
|
|
|
// Returns whether or not a given point is inside any colliding tile. If
|
|
// collisionSet is Dynamic or Static, then does not intersect with platforms.
|
|
virtual bool pointTileCollision(Vec2F const& point, CollisionSet const& collisionSet = DefaultCollisionSet) const = 0;
|
|
|
|
// Returns whether line intersects with any colliding tiles.
|
|
virtual bool lineTileCollision(Vec2F const& begin, Vec2F const& end, CollisionSet const& collisionSet = DefaultCollisionSet) const = 0;
|
|
virtual Maybe<pair<Vec2F, Vec2I>> lineTileCollisionPoint(Vec2F const& begin, Vec2F const& end, CollisionSet const& collisionSet = DefaultCollisionSet) const = 0;
|
|
|
|
// Returns a list of all the collidable tiles along the given line.
|
|
virtual List<Vec2I> collidingTilesAlongLine(Vec2F const& begin, Vec2F const& end, CollisionSet const& collisionSet = DefaultCollisionSet, int maxSize = -1, bool includeEdges = true) const = 0;
|
|
|
|
// Returns whether the given rect contains any colliding tiles.
|
|
virtual bool rectTileCollision(RectI const& region, CollisionSet const& collisionSet = DefaultCollisionSet) const = 0;
|
|
|
|
// Damage multiple tiles, avoiding duplication (objects or plants that occupy
|
|
// more than one tile
|
|
// position are only damaged once)
|
|
virtual TileDamageResult damageTiles(List<Vec2I> const& tilePositions, TileLayer layer, Vec2F const& sourcePosition, TileDamage const& tileDamage, Maybe<EntityId> sourceEntity = {}) = 0;
|
|
|
|
virtual InteractiveEntityPtr getInteractiveInRange(Vec2F const& targetPosition, Vec2F const& sourcePosition, float maxRange) const = 0;
|
|
// Can the target entity be reached from the given position within the given radius?
|
|
virtual bool canReachEntity(Vec2F const& position, float radius, EntityId targetEntity, bool preferInteractive = true) const = 0;
|
|
virtual RpcPromise<InteractAction> interact(InteractRequest const& request) = 0;
|
|
|
|
virtual float gravity(Vec2F const& pos) const = 0;
|
|
virtual float windLevel(Vec2F const& pos) const = 0;
|
|
virtual float lightLevel(Vec2F const& pos) const = 0;
|
|
virtual bool breathable(Vec2F const& pos) const = 0;
|
|
virtual float threatLevel() const = 0;
|
|
virtual StringList environmentStatusEffects(Vec2F const& pos) const = 0;
|
|
virtual StringList weatherStatusEffects(Vec2F const& pos) const = 0;
|
|
virtual bool exposedToWeather(Vec2F const& pos) const = 0;
|
|
virtual bool isUnderground(Vec2F const& pos) const = 0;
|
|
virtual bool disableDeathDrops() const = 0;
|
|
virtual List<PhysicsForceRegion> forceRegions() const = 0;
|
|
|
|
// Gets / sets world-wide properties
|
|
virtual Json getProperty(String const& propertyName, Json const& def = {}) const = 0;
|
|
virtual void setProperty(String const& propertyName, Json const& property) = 0;
|
|
|
|
virtual void timer(int stepsDelay, WorldAction worldAction) = 0;
|
|
virtual double epochTime() const = 0;
|
|
virtual uint32_t day() const = 0;
|
|
virtual float dayLength() const = 0;
|
|
virtual float timeOfDay() const = 0;
|
|
|
|
virtual LuaRootPtr luaRoot() = 0;
|
|
|
|
// Locate a unique entity, if the target is local, the promise will be
|
|
// finished before being returned. If the unique entity is not found, the
|
|
// promise will fail.
|
|
virtual RpcPromise<Vec2F> findUniqueEntity(String const& uniqueEntityId) = 0;
|
|
|
|
// Send a message to a local or remote scripted entity. If the target is
|
|
// local, the promise will be finished before being returned. Entity id can
|
|
// either be EntityId or a uniqueId.
|
|
virtual RpcPromise<Json> sendEntityMessage(Variant<EntityId, String> const& entity, String const& message, JsonArray const& args = {}) = 0;
|
|
|
|
// Helper non-virtual methods.
|
|
|
|
bool isServer() const;
|
|
bool isClient() const;
|
|
|
|
List<EntityPtr> entityQuery(RectF const& boundBox, EntityFilter selector = {}) const;
|
|
List<EntityPtr> entityLineQuery(Vec2F const& begin, Vec2F const& end, EntityFilter selector = {}) const;
|
|
|
|
List<TileEntityPtr> entitiesAtTile(Vec2I const& pos, EntityFilter filter = EntityFilter()) const;
|
|
|
|
// Find tiles near the given point that are not occupied (according to
|
|
// tileIsOccupied)
|
|
List<Vec2I> findEmptyTiles(Vec2I pos, unsigned maxDist = 5, size_t maxAmount = 1, bool excludeEphemeral = false) const;
|
|
|
|
// Do tile modification that only uses a single tile.
|
|
bool canModifyTile(Vec2I const& pos, TileModification const& modification, bool allowEntityOverlap) const;
|
|
bool modifyTile(Vec2I const& pos, TileModification const& modification, bool allowEntityOverlap);
|
|
|
|
TileDamageResult damageTile(Vec2I const& tilePosition, TileLayer layer, Vec2F const& sourcePosition, TileDamage const& tileDamage, Maybe<EntityId> sourceEntity = {});
|
|
|
|
// Returns closest entity for which lineCollision between the given center
|
|
// position and the entity position returns false.
|
|
EntityPtr closestEntityInSight(Vec2F const& center, float radius, CollisionSet const& collisionSet = DefaultCollisionSet, EntityFilter selector = {}) const;
|
|
|
|
// Returns whether point collides with any collision geometry.
|
|
bool pointCollision(Vec2F const& point, CollisionSet const& collisionSet = DefaultCollisionSet) const;
|
|
|
|
// Returns first point along line that collides with any collision geometry, along
|
|
// with the normal of the intersected line, if any.
|
|
Maybe<pair<Vec2F, Maybe<Vec2F>>> lineCollision(Line2F const& line, CollisionSet const& collisionSet = DefaultCollisionSet) const;
|
|
|
|
// Returns whether poly collides with any collision geometry.
|
|
bool polyCollision(PolyF const& poly, CollisionSet const& collisionSet = DefaultCollisionSet) const;
|
|
|
|
// Helper template methods. Only queries entities of the given template
|
|
// type, and casts them to the appropriate pointer type.
|
|
|
|
template <typename EntityT>
|
|
shared_ptr<EntityT> get(EntityId entityId) const;
|
|
|
|
template <typename EntityT>
|
|
List<shared_ptr<EntityT>> query(RectF const& boundBox, EntityFilterOf<EntityT> selector = {}) const;
|
|
|
|
template <typename EntityT>
|
|
shared_ptr<EntityT> closest(Vec2F const& center, float radius, EntityFilterOf<EntityT> selector = {}) const;
|
|
|
|
template <typename EntityT>
|
|
shared_ptr<EntityT> closestInSight(Vec2F const& center, float radius, CollisionSet const& collisionSet, EntityFilterOf<EntityT> selector = {}) const;
|
|
|
|
template <typename EntityT>
|
|
List<shared_ptr<EntityT>> lineQuery(Vec2F const& begin, Vec2F const& end, EntityFilterOf<EntityT> selector = {}) const;
|
|
|
|
template <typename EntityT>
|
|
List<shared_ptr<EntityT>> atTile(Vec2I const& pos) const;
|
|
};
|
|
|
|
template <typename EntityT>
|
|
shared_ptr<EntityT> World::get(EntityId entityId) const {
|
|
return as<EntityT>(entity(entityId));
|
|
}
|
|
|
|
template <typename EntityT>
|
|
List<shared_ptr<EntityT>> World::query(RectF const& boundBox, EntityFilterOf<EntityT> selector) const {
|
|
List<shared_ptr<EntityT>> list;
|
|
forEachEntity(boundBox, [&](EntityPtr const& entity) {
|
|
if (auto e = as<EntityT>(entity)) {
|
|
if (!selector || selector(e))
|
|
list.append(std::move(e));
|
|
}
|
|
});
|
|
|
|
return list;
|
|
}
|
|
|
|
template <typename EntityT>
|
|
shared_ptr<EntityT> World::closest(Vec2F const& center, float radius, EntityFilterOf<EntityT> selector) const {
|
|
return as<EntityT>(closestEntity(center, radius, entityTypeFilter<EntityT>(selector)));
|
|
}
|
|
|
|
template <typename EntityT>
|
|
shared_ptr<EntityT> World::closestInSight(
|
|
Vec2F const& center, float radius, CollisionSet const& collisionSet, EntityFilterOf<EntityT> selector) const {
|
|
return as<EntityT>(closestEntityInSight(center, radius, collisionSet, entityTypeFilter<EntityT>(selector)));
|
|
}
|
|
|
|
template <typename EntityT>
|
|
List<shared_ptr<EntityT>> World::lineQuery(
|
|
Vec2F const& begin, Vec2F const& end, EntityFilterOf<EntityT> selector) const {
|
|
List<shared_ptr<EntityT>> list;
|
|
forEachEntityLine(begin, end, [&](EntityPtr entity) {
|
|
if (auto e = as<EntityT>(std::move(entity))) {
|
|
if (!selector || selector(e))
|
|
list.append(std::move(e));
|
|
}
|
|
});
|
|
|
|
return list;
|
|
}
|
|
|
|
template <typename EntityT>
|
|
List<shared_ptr<EntityT>> World::atTile(Vec2I const& pos) const {
|
|
List<shared_ptr<EntityT>> list;
|
|
forEachEntityAtTile(pos, [&](TileEntityPtr const& entity) {
|
|
if (auto e = as<EntityT>(entity))
|
|
list.append(std::move(e));
|
|
});
|
|
return list;
|
|
}
|
|
}
|
|
|
|
#endif
|