Predict placed tile collision

This commit is contained in:
Kae 2023-08-19 12:55:32 +10:00
parent 1af5e5cc89
commit 0c74c70475
2 changed files with 20 additions and 7 deletions

View File

@ -55,6 +55,12 @@ WorldClient::WorldClient(PlayerPtr mainPlayer) {
centerClientWindowOnPlayer(Vec2U(100, 100)); centerClientWindowOnPlayer(Vec2U(100, 100));
m_collisionGenerator.init([this](int x, int y) { m_collisionGenerator.init([this](int x, int y) {
if (!m_predictedTiles.empty()) {
if (auto p = m_predictedTiles.ptr({x, y})) {
if (p->collision)
return *p->collision;
}
}
return m_tileArray->tile({x, y}).collision; return m_tileArray->tile({x, y}).collision;
}); });
@ -811,8 +817,9 @@ void WorldClient::handleIncomingPackets(List<PacketPtr> const& packets) {
for (int x = tileRegion.xMin(); x < tileRegion.xMax(); ++x) { for (int x = tileRegion.xMin(); x < tileRegion.xMax(); ++x) {
for (int y = tileRegion.yMin(); y < tileRegion.yMax(); ++y) for (int y = tileRegion.yMin(); y < tileRegion.yMax(); ++y)
readNetTile({x, y}, tileArrayUpdate->array(x - tileRegion.xMin(), y - tileRegion.yMin())); readNetTile({x, y}, tileArrayUpdate->array(x - tileRegion.xMin(), y - tileRegion.yMin()), false);
} }
dirtyCollision(tileRegion);
} else if (auto tileUpdate = as<TileUpdatePacket>(packet)) { } else if (auto tileUpdate = as<TileUpdatePacket>(packet)) {
readNetTile(tileUpdate->position, tileUpdate->tile); readNetTile(tileUpdate->position, tileUpdate->tile);
@ -840,6 +847,7 @@ void WorldClient::handleIncomingPackets(List<PacketPtr> const& packets) {
if (placeMaterial->layer == TileLayer::Foreground) { if (placeMaterial->layer == TileLayer::Foreground) {
p.foreground.reset(); p.foreground.reset();
p.foregroundHueShift.reset(); p.foregroundHueShift.reset();
p.collision.reset();
} }
else { else {
p.background.reset(); p.background.reset();
@ -1827,7 +1835,7 @@ BiomeConstPtr WorldClient::mainEnvironmentBiome() const {
return m_worldTemplate->environmentBiome(pos[0], pos[1]); return m_worldTemplate->environmentBiome(pos[0], pos[1]);
} }
bool WorldClient::readNetTile(Vec2I const& pos, NetTile const& netTile) { bool WorldClient::readNetTile(Vec2I const& pos, NetTile const& netTile, bool updateCollision) {
ClientTile* tile = m_tileArray->modifyTile(pos); ClientTile* tile = m_tileArray->modifyTile(pos);
if (!tile) if (!tile)
return false; return false;
@ -1837,6 +1845,8 @@ bool WorldClient::readNetTile(Vec2I const& pos, NetTile const& netTile) {
if (findPrediction != m_predictedTiles.end()) { if (findPrediction != m_predictedTiles.end()) {
auto& p = findPrediction->second; auto& p = findPrediction->second;
if (p.collision && *p.collision == netTile.collision)
p.collision.reset();
if (p.foreground && *p.foreground == netTile.foreground) if (p.foreground && *p.foreground == netTile.foreground)
p.foreground.reset(); p.foreground.reset();
if (p.foregroundMod && *p.foregroundMod == netTile.foregroundMod) if (p.foregroundMod && *p.foregroundMod == netTile.foregroundMod)
@ -1881,6 +1891,7 @@ bool WorldClient::readNetTile(Vec2I const& pos, NetTile const& netTile) {
tile->foregroundLightTransparent = tile->foregroundLightTransparent =
materialDatabase->foregroundLightTransparent(tile->foreground) && tile->collision != CollisionKind::Dynamic; materialDatabase->foregroundLightTransparent(tile->foreground) && tile->collision != CollisionKind::Dynamic;
if (updateCollision)
dirtyCollision(RectI::withSize(pos, {1, 1})); dirtyCollision(RectI::withSize(pos, {1, 1}));
return true; return true;
@ -1923,7 +1934,7 @@ void WorldClient::freshenCollision(RectI const& region) {
} }
} }
for (auto collisionBlock : m_collisionGenerator.getBlocks(freshenRegion)) { for (auto& collisionBlock : m_collisionGenerator.getBlocks(freshenRegion)) {
if (auto tile = m_tileArray->modifyTile(collisionBlock.space)) if (auto tile = m_tileArray->modifyTile(collisionBlock.space))
tile->collisionCache.append(move(collisionBlock)); tile->collisionCache.append(move(collisionBlock));
} }
@ -2213,6 +2224,8 @@ void WorldClient::informTilePrediction(Vec2I const& pos, TileModification const&
if (placeMaterial->layer == TileLayer::Foreground) { if (placeMaterial->layer == TileLayer::Foreground) {
p.foreground = placeMaterial->material; p.foreground = placeMaterial->material;
p.foregroundHueShift = placeMaterial->materialHueShift; p.foregroundHueShift = placeMaterial->materialHueShift;
p.collision = Root::singleton().materialDatabase()->materialCollisionKind(placeMaterial->material);
dirtyCollision(RectI::withSize(pos, { 1, 1 }));
} else { } else {
p.background = placeMaterial->material; p.background = placeMaterial->material;
p.backgroundHueShift = placeMaterial->materialHueShift; p.backgroundHueShift = placeMaterial->materialHueShift;

View File

@ -233,7 +233,7 @@ private:
// Populates foregroundTransparent / backgroundTransparent flag on ClientTile // Populates foregroundTransparent / backgroundTransparent flag on ClientTile
// based on transparency rules. // based on transparency rules.
bool readNetTile(Vec2I const& pos, NetTile const& netTile); bool readNetTile(Vec2I const& pos, NetTile const& netTile, bool updateCollision = true);
void dirtyCollision(RectI const& region); void dirtyCollision(RectI const& region);
void freshenCollision(RectI const& region); void freshenCollision(RectI const& region);
void renderCollisionDebug(); void renderCollisionDebug();