v1.4.4
This commit is contained in:
commit
9c94d113d3
10260 changed files with 1237388 additions and 0 deletions
153
source/game/interfaces/StarWorld.cpp
Normal file
153
source/game/interfaces/StarWorld.cpp
Normal file
|
@ -0,0 +1,153 @@
|
|||
#include "StarWorld.hpp"
|
||||
#include "StarScriptedEntity.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
bool World::isServer() const {
|
||||
return connection() == ServerConnectionId;
|
||||
}
|
||||
|
||||
bool World::isClient() const {
|
||||
return !isServer();
|
||||
}
|
||||
|
||||
List<EntityPtr> World::entityQuery(RectF const& boundBox, EntityFilter selector) const {
|
||||
List<EntityPtr> list;
|
||||
forEachEntity(boundBox, [&](EntityPtr const& entity) {
|
||||
if (!selector || selector(entity))
|
||||
list.append(entity);
|
||||
});
|
||||
return list;
|
||||
}
|
||||
|
||||
List<EntityPtr> World::entityLineQuery(Vec2F const& begin, Vec2F const& end, EntityFilter selector) const {
|
||||
List<EntityPtr> list;
|
||||
forEachEntityLine(begin, end, [&](EntityPtr const& entity) {
|
||||
if (!selector || selector(entity))
|
||||
list.append(entity);
|
||||
});
|
||||
return list;
|
||||
}
|
||||
|
||||
List<TileEntityPtr> World::entitiesAtTile(Vec2I const& pos, EntityFilter selector) const {
|
||||
List<TileEntityPtr> list;
|
||||
forEachEntityAtTile(pos, [&](TileEntityPtr entity) {
|
||||
if (!selector || selector(entity))
|
||||
list.append(move(entity));
|
||||
});
|
||||
return list;
|
||||
}
|
||||
|
||||
List<Vec2I> World::findEmptyTiles(Vec2I pos, unsigned maxDist, size_t maxAmount, bool excludeEphemeral) const {
|
||||
List<Vec2I> res;
|
||||
if (!tileIsOccupied(pos, TileLayer::Foreground, excludeEphemeral))
|
||||
res.append(pos);
|
||||
|
||||
if (res.size() >= maxAmount)
|
||||
return res;
|
||||
|
||||
// searches manhattan distance counterclockwise from right
|
||||
for (int distance = 1; distance <= (int)maxDist; distance++) {
|
||||
const int totalSpots = 4 * distance;
|
||||
int xDiff = distance;
|
||||
int yDiff = 0;
|
||||
int dx = -1;
|
||||
int dy = 1;
|
||||
for (int i = 0; i < totalSpots; i++) {
|
||||
if (!tileIsOccupied(pos + Vec2I(xDiff, yDiff), TileLayer::Foreground)) {
|
||||
res.append(pos + Vec2I(xDiff, yDiff));
|
||||
if (res.size() >= maxAmount) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
xDiff += dx;
|
||||
yDiff += dy;
|
||||
if (abs(xDiff) == distance)
|
||||
dx *= -1;
|
||||
if (abs(yDiff) == distance)
|
||||
dy *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool World::canModifyTile(Vec2I const& pos, TileModification const& modification, bool allowEntityOverlap) const {
|
||||
return !validTileModifications({{pos, modification}}, allowEntityOverlap).empty();
|
||||
}
|
||||
|
||||
bool World::modifyTile(Vec2I const& pos, TileModification const& modification, bool allowEntityOverlap) {
|
||||
return applyTileModifications({{pos, modification}}, allowEntityOverlap).empty();
|
||||
}
|
||||
|
||||
TileDamageResult World::damageTile(Vec2I const& tilePosition, TileLayer layer, Vec2F const& sourcePosition, TileDamage const& tileDamage, Maybe<EntityId> sourceEntity) {
|
||||
return damageTiles({tilePosition}, layer, sourcePosition, tileDamage, sourceEntity);
|
||||
}
|
||||
|
||||
EntityPtr World::closestEntityInSight(Vec2F const& center, float radius, CollisionSet const& collisionSet, EntityFilter selector) const {
|
||||
return closestEntity(center, radius, [=](EntityPtr const& entity) {
|
||||
return selector(entity) && !lineTileCollision(center, entity->position(), collisionSet);
|
||||
});
|
||||
}
|
||||
|
||||
bool World::pointCollision(Vec2F const& point, CollisionSet const& collisionSet) const {
|
||||
bool collided = false;
|
||||
|
||||
forEachCollisionBlock(RectI::withCenter(Vec2I(point), {3, 3}), [&](CollisionBlock const& block) {
|
||||
if (collided || !isColliding(block.kind, collisionSet))
|
||||
return;
|
||||
|
||||
if (block.poly.contains(point))
|
||||
collided = true;
|
||||
});
|
||||
|
||||
return collided;
|
||||
}
|
||||
|
||||
Maybe<pair<Vec2F, Maybe<Vec2F>>> World::lineCollision(Line2F const& line, CollisionSet const& collisionSet) const {
|
||||
auto geometry = this->geometry();
|
||||
Maybe<PolyF> intersectPoly;
|
||||
Maybe<PolyF::LineIntersectResult> closestIntersection;
|
||||
|
||||
forEachCollisionBlock(RectI::integral(RectF::boundBoxOf(line.min(), line.max()).padded(1)), [&](CollisionBlock const& block) {
|
||||
if (block.poly.isNull() || !isColliding(block.kind, collisionSet))
|
||||
return;
|
||||
|
||||
Vec2F nearMin = geometry.nearestTo(block.poly.center(), line.min());
|
||||
auto intersection = block.poly.lineIntersection(Line2F(nearMin, nearMin + line.diff()));
|
||||
if (intersection && (!closestIntersection || intersection->along < closestIntersection->along)) {
|
||||
intersectPoly = block.poly;
|
||||
closestIntersection = intersection;
|
||||
}
|
||||
});
|
||||
|
||||
if (closestIntersection) {
|
||||
auto point = line.eval(closestIntersection->along);
|
||||
auto normal = closestIntersection->intersectedSide.apply([&](uint64_t side) { return intersectPoly->normal(side); });
|
||||
return make_pair(point, normal);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
bool World::polyCollision(PolyF const& poly, CollisionSet const& collisionSet) const {
|
||||
auto geometry = this->geometry();
|
||||
Vec2F polyCenter = poly.center();
|
||||
PolyF translatedPoly;
|
||||
bool collided = false;
|
||||
|
||||
forEachCollisionBlock(RectI::integral(poly.boundBox()).padded(1), [&](CollisionBlock const& block) {
|
||||
if (collided || !isColliding(block.kind, collisionSet))
|
||||
return;
|
||||
|
||||
Vec2F center = block.poly.center();
|
||||
Vec2F newCenter = geometry.nearestTo(polyCenter, center);
|
||||
translatedPoly = block.poly;
|
||||
translatedPoly.translate(newCenter - center);
|
||||
if (poly.intersects(translatedPoly))
|
||||
collided = true;
|
||||
});
|
||||
|
||||
return collided;
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue