Fix more cases of tile collision not taking object material spaces into account

Fixes #53
This commit is contained in:
Kae 2024-04-01 10:30:03 +11:00
parent b556f71473
commit 02632b248c
6 changed files with 15 additions and 10 deletions

View File

@ -49,7 +49,7 @@ void ParticleManager::update(float dt, RectF const& cullRegion, float wind) {
Vec2I pos(particle.position.floor());
TileType tiletype;
auto const& tile = m_tileSectorArray->tile(pos);
if (isSolidColliding(tile.collision))
if (isSolidColliding(tile.getCollision()))
tiletype = TileType::Colliding;
else if (tile.liquid.level > 0.5f)
tiletype = TileType::Water;

View File

@ -256,7 +256,7 @@ void WorldClient::forEachCollisionBlock(RectI const& region, function<void(Colli
const_cast<WorldClient*>(this)->freshenCollision(region);
m_tileArray->tileEach(region, [iterator](Vec2I const& pos, ClientTile const& tile) {
if (tile.collision == CollisionKind::Null) {
if (tile.getCollision() == CollisionKind::Null) {
iterator(CollisionBlock::nullBlock(pos));
} else {
starAssert(!tile.collisionCacheDirty);
@ -1760,7 +1760,7 @@ void WorldClient::initWorld(WorldStartPacket const& startPacket) {
m_weather.setup(m_geometry, [this](Vec2I const& pos) {
auto const& tile = m_tileArray->tile(pos);
return !isRealMaterial(tile.background) && !isSolidColliding(tile.collision);
return !isRealMaterial(tile.background) && !isSolidColliding(tile.getCollision());
});
m_weather.readUpdate(startPacket.weatherData);

View File

@ -596,7 +596,7 @@ bool SpawnerWorld::spawningProhibited(RectF const& area) const {
for (int x = region.xMin(); x < region.xMax(); ++x) {
for (int y = region.yMin(); y < region.yMax(); ++y) {
auto const& tile = m_worldServer->getServerTile({x, y});
if (tile.collision == CollisionKind::Null || tile.dungeonId != NoDungeonId)
if (tile.getCollision() == CollisionKind::Null || tile.dungeonId != NoDungeonId)
return true;
}
}

View File

@ -86,7 +86,7 @@ namespace WorldImpl {
Vec2I const& pos, TileLayer layer, bool includeEphemeral, bool checkCollision) {
auto& tile = tileSectorArray->tile(pos);
if (layer == TileLayer::Foreground)
return (checkCollision ? tile.collision >= CollisionKind::Dynamic : tile.foreground != EmptyMaterialId) || entityMap->tileIsOccupied(pos, includeEphemeral);
return (checkCollision ? tile.getCollision() >= CollisionKind::Dynamic : tile.foreground != EmptyMaterialId) || entityMap->tileIsOccupied(pos, includeEphemeral);
else
return tile.background != EmptyMaterialId;
}
@ -94,13 +94,13 @@ namespace WorldImpl {
template <typename TileSectorArray>
CollisionKind tileCollisionKind(shared_ptr<TileSectorArray> const& tileSectorArray, EntityMapPtr const&,
Vec2I const& pos) {
return tileSectorArray->tile(pos).collision;
return tileSectorArray->tile(pos).getCollision();
}
template <typename TileSectorArray>
bool rectTileCollision(shared_ptr<TileSectorArray> const& tileSectorArray, RectI const& region, CollisionSet const& collisionSet) {
return tileSectorArray->tileSatisfies(region, [&collisionSet](Vec2I const&, typename TileSectorArray::Tile const& tile) {
return isColliding(tile.collision, collisionSet);
return isColliding(tile.getCollision(), collisionSet);
});
}
@ -398,7 +398,7 @@ namespace WorldImpl {
auto tile = tileSectorArray->tile(ipos);
bool environmentBreathable = breathableMap.maybe(tile.dungeonId).value(worldTemplate->breathable(ipos[0], ipos[1]));
bool liquidBreathable = remainder >= tile.liquid.level;
bool foregroundBreathable = tile.collision != CollisionKind::Block || !world->pointCollision(pos);
bool foregroundBreathable = tile.getCollision() != CollisionKind::Block || !world->pointCollision(pos);
return environmentBreathable && foregroundBreathable && liquidBreathable;
}
@ -429,7 +429,7 @@ namespace WorldImpl {
bool backgroundTransparent = materialDatabase->backgroundLightTransparent(tile.background);
bool foregroundTransparent = materialDatabase->foregroundLightTransparent(tile.foreground)
&& tile.collision != CollisionKind::Dynamic;
&& tile.getCollision() != CollisionKind::Dynamic;
cell = {materialDatabase->radiantLight(tile.foreground, tile.foregroundMod).sum() / 3.0f, !foregroundTransparent};
cell.light += liquidsDatabase->radiantLight(tile.liquid).sum() / 3.0f;

View File

@ -783,7 +783,7 @@ CollisionKind WorldServer::tileCollisionKind(Vec2I const& pos) const {
void WorldServer::forEachCollisionBlock(RectI const& region, function<void(CollisionBlock const&)> const& iterator) const {
const_cast<WorldServer*>(this)->freshenCollision(region);
m_tileArray->tileEach(region, [iterator](Vec2I const& pos, ServerTile const& tile) {
if (tile.collision == CollisionKind::Null) {
if (tile.getCollision() == CollisionKind::Null) {
iterator(CollisionBlock::nullBlock(pos));
} else {
starAssert(!tile.collisionCacheDirty);

View File

@ -21,6 +21,7 @@ struct WorldTile {
MaterialId material(TileLayer layer) const;
ModId mod(TileLayer layer) const;
MaterialColorVariant materialColor(TileLayer layer) const;
CollisionKind getCollision() const;
tuple<MaterialId, MaterialHue, MaterialColorVariant> materialAndColor(TileLayer layer) const;
bool isConnectable(TileLayer layer, bool materialOnly) const;
bool isColliding(CollisionSet const& collisionSet) const;
@ -265,6 +266,10 @@ inline MaterialColorVariant WorldTile::materialColor(TileLayer layer) const {
return backgroundColorVariant;
}
inline CollisionKind WorldTile::getCollision() const {
return collision;
}
inline tuple<MaterialId, MaterialHue, MaterialColorVariant> WorldTile::materialAndColor(TileLayer layer) const {
if (layer == TileLayer::Foreground)
return std::tuple<MaterialId, MaterialHue, MaterialColorVariant>{