hopefully fix #33
in OpenStarbound, players can place blocks with their own collision type. this can cause objects to override the collision type if the object has material spaces and a previous attempt at accounting for this led to that bug: giving object collision its own field in the server tile should fix this
This commit is contained in:
parent
165bcbefee
commit
dc77061840
@ -681,7 +681,7 @@ ByteArray Assets::read(String const& path) const {
|
|||||||
Json Assets::checkPatchArray(String const& path, AssetSourcePtr const& source, Json const result, JsonArray const patchData, Maybe<Json> const external) const {
|
Json Assets::checkPatchArray(String const& path, AssetSourcePtr const& source, Json const result, JsonArray const patchData, Maybe<Json> const external) const {
|
||||||
auto externalRef = external.value();
|
auto externalRef = external.value();
|
||||||
auto newResult = result;
|
auto newResult = result;
|
||||||
for (auto const patch : patchData) {
|
for (auto const& patch : patchData) {
|
||||||
switch(patch.type()) {
|
switch(patch.type()) {
|
||||||
case Json::Type::Array: // if the patch is an array, go down recursively until we get objects
|
case Json::Type::Array: // if the patch is an array, go down recursively until we get objects
|
||||||
try {
|
try {
|
||||||
|
@ -1255,7 +1255,7 @@ void WorldServer::init(bool firstTime) {
|
|||||||
m_entityMessageResponses = {};
|
m_entityMessageResponses = {};
|
||||||
|
|
||||||
m_collisionGenerator.init([=](int x, int y) {
|
m_collisionGenerator.init([=](int x, int y) {
|
||||||
return m_tileArray->tile({x, y}).collision;
|
return m_tileArray->tile({x, y}).getCollision();
|
||||||
});
|
});
|
||||||
|
|
||||||
m_tileEntityBreakCheckTimer = GameTimer(m_serverConfig.getFloat("tileEntityBreakCheckInterval"));
|
m_tileEntityBreakCheckTimer = GameTimer(m_serverConfig.getFloat("tileEntityBreakCheckInterval"));
|
||||||
@ -1505,21 +1505,20 @@ void WorldServer::updateTileEntityTiles(TileEntityPtr const& entity, bool removi
|
|||||||
|
|
||||||
ServerTile* tile = m_tileArray->modifyTile(pos);
|
ServerTile* tile = m_tileArray->modifyTile(pos);
|
||||||
if (tile) {
|
if (tile) {
|
||||||
bool updated = false;
|
tile->rootSource = {};
|
||||||
|
bool updatedTile = false;
|
||||||
if (tile->foreground == materialSpace.material) {
|
if (tile->foreground == materialSpace.material) {
|
||||||
tile->foreground = EmptyMaterialId;
|
tile->foreground = EmptyMaterialId;
|
||||||
tile->foregroundMod = NoModId;
|
tile->foregroundMod = NoModId;
|
||||||
tile->rootSource = {};
|
updatedTile = true;
|
||||||
updated = true;
|
|
||||||
}
|
}
|
||||||
if (tile->collision == materialDatabase->materialCollisionKind(materialSpace.material)
|
if (tile->updateObjectCollision(CollisionKind::None)) {
|
||||||
&& tile->updateCollision(materialSpace.prevCollision.value(CollisionKind::None))) {
|
|
||||||
m_liquidEngine->visitLocation(pos);
|
m_liquidEngine->visitLocation(pos);
|
||||||
m_fallingBlocksAgent->visitLocation(pos);
|
m_fallingBlocksAgent->visitLocation(pos);
|
||||||
dirtyCollision(RectI::withSize(pos, { 1, 1 }));
|
dirtyCollision(RectI::withSize(pos, { 1, 1 }));
|
||||||
updated = true;
|
updatedTile = true;
|
||||||
}
|
}
|
||||||
if (updated)
|
if (updatedTile)
|
||||||
queueTileUpdates(pos);
|
queueTileUpdates(pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1533,35 +1532,27 @@ void WorldServer::updateTileEntityTiles(TileEntityPtr const& entity, bool removi
|
|||||||
for (auto const& materialSpace : newMaterialSpaces) {
|
for (auto const& materialSpace : newMaterialSpaces) {
|
||||||
Vec2I pos = materialSpace.space + entity->tilePosition();
|
Vec2I pos = materialSpace.space + entity->tilePosition();
|
||||||
|
|
||||||
bool updated = false;
|
bool updatedTile = false;
|
||||||
bool updatedCollision = false;
|
bool updatedCollision = false;
|
||||||
ServerTile* tile = m_tileArray->modifyTile(pos);
|
ServerTile* tile = m_tileArray->modifyTile(pos);
|
||||||
if (tile && (tile->foreground == EmptyMaterialId || tile->foreground == materialSpace.material)) {
|
if (tile) {
|
||||||
|
if (tile->foreground == EmptyMaterialId) {
|
||||||
tile->foreground = materialSpace.material;
|
tile->foreground = materialSpace.material;
|
||||||
tile->foregroundMod = NoModId;
|
tile->foregroundMod = NoModId;
|
||||||
|
updatedTile = true;
|
||||||
|
}
|
||||||
bool hadRoot = tile->rootSource.isValid();
|
bool hadRoot = tile->rootSource.isValid();
|
||||||
if (isRealMaterial(materialSpace.material))
|
if (isRealMaterial(materialSpace.material))
|
||||||
tile->rootSource = entity->tilePosition();
|
tile->rootSource = entity->tilePosition();
|
||||||
auto& space = passedSpaces.emplaceAppend(materialSpace);
|
auto& space = passedSpaces.emplaceAppend(materialSpace);
|
||||||
if (hadRoot)
|
updatedTile |= updatedCollision = tile->updateObjectCollision(materialDatabase->materialCollisionKind(materialSpace.material));
|
||||||
space.prevCollision.emplace(tile->collision);
|
|
||||||
updatedCollision = tile->updateCollision(materialDatabase->materialCollisionKind(tile->foreground));
|
|
||||||
updated = true;
|
|
||||||
}
|
|
||||||
else if (tile && tile->collision < CollisionKind::Dynamic) {
|
|
||||||
bool hadRoot = tile->rootSource.isValid();
|
|
||||||
auto& space = passedSpaces.emplaceAppend(materialSpace);
|
|
||||||
if (hadRoot)
|
|
||||||
space.prevCollision.emplace(tile->collision);
|
|
||||||
updatedCollision = tile->updateCollision(materialDatabase->materialCollisionKind(materialSpace.material));
|
|
||||||
updated = true;
|
|
||||||
}
|
}
|
||||||
if (updatedCollision) {
|
if (updatedCollision) {
|
||||||
m_liquidEngine->visitLocation(pos);
|
m_liquidEngine->visitLocation(pos);
|
||||||
m_fallingBlocksAgent->visitLocation(pos);
|
m_fallingBlocksAgent->visitLocation(pos);
|
||||||
dirtyCollision(RectI::withSize(pos, { 1, 1 }));
|
dirtyCollision(RectI::withSize(pos, { 1, 1 }));
|
||||||
}
|
}
|
||||||
if (updated)
|
if (updatedTile)
|
||||||
queueTileUpdates(pos);
|
queueTileUpdates(pos);
|
||||||
}
|
}
|
||||||
spaces.materials = std::move(passedSpaces);
|
spaces.materials = std::move(passedSpaces);
|
||||||
@ -1997,7 +1988,7 @@ void WorldServer::writeNetTile(Vec2I const& pos, NetTile& netTile) const {
|
|||||||
netTile.backgroundMod = tile.backgroundMod;
|
netTile.backgroundMod = tile.backgroundMod;
|
||||||
netTile.backgroundModHueShift = tile.backgroundModHueShift;
|
netTile.backgroundModHueShift = tile.backgroundModHueShift;
|
||||||
netTile.liquid = tile.liquid.netUpdate();
|
netTile.liquid = tile.liquid.netUpdate();
|
||||||
netTile.collision = tile.collision;
|
netTile.collision = tile.getCollision();
|
||||||
netTile.blockBiomeIndex = tile.blockBiomeIndex;
|
netTile.blockBiomeIndex = tile.blockBiomeIndex;
|
||||||
netTile.environmentBiomeIndex = tile.environmentBiomeIndex;
|
netTile.environmentBiomeIndex = tile.environmentBiomeIndex;
|
||||||
netTile.dungeonId = tile.dungeonId;
|
netTile.dungeonId = tile.dungeonId;
|
||||||
|
@ -26,7 +26,7 @@ bool WorldTile::isColliding(CollisionSet const& collisionSet) const {
|
|||||||
|
|
||||||
VersionNumber const ServerTile::CurrentSerializationVersion = 418;
|
VersionNumber const ServerTile::CurrentSerializationVersion = 418;
|
||||||
|
|
||||||
ServerTile::ServerTile() {}
|
ServerTile::ServerTile() : objectCollision(CollisionKind::None) {}
|
||||||
|
|
||||||
ServerTile::ServerTile(ServerTile const& serverTile) : WorldTile() {
|
ServerTile::ServerTile(ServerTile const& serverTile) : WorldTile() {
|
||||||
*this = serverTile;
|
*this = serverTile;
|
||||||
@ -37,7 +37,7 @@ ServerTile& ServerTile::operator=(ServerTile const& serverTile) {
|
|||||||
|
|
||||||
liquid = serverTile.liquid;
|
liquid = serverTile.liquid;
|
||||||
rootSource = serverTile.rootSource;
|
rootSource = serverTile.rootSource;
|
||||||
|
objectCollision = serverTile.objectCollision;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,6 +109,25 @@ bool ServerTile::updateCollision(CollisionKind kind) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ServerTile::updateObjectCollision(CollisionKind kind) {
|
||||||
|
if (objectCollision != kind) {
|
||||||
|
objectCollision = kind;
|
||||||
|
collisionCacheDirty = true;
|
||||||
|
collisionCache.clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CollisionKind ServerTile::getCollision() const {
|
||||||
|
CollisionKind kind = collision;
|
||||||
|
if (objectCollision != CollisionKind::None
|
||||||
|
&& (objectCollision != CollisionKind::Platform || kind == CollisionKind::None)) {
|
||||||
|
kind = objectCollision;
|
||||||
|
}
|
||||||
|
return kind;
|
||||||
|
}
|
||||||
|
|
||||||
PredictedTile::operator bool() const {
|
PredictedTile::operator bool() const {
|
||||||
return
|
return
|
||||||
background
|
background
|
||||||
|
@ -69,12 +69,20 @@ struct ServerTile : public WorldTile {
|
|||||||
// Updates collision, clears cache, and if the collision kind does not
|
// Updates collision, clears cache, and if the collision kind does not
|
||||||
// support liquid destroys it.
|
// support liquid destroys it.
|
||||||
bool updateCollision(CollisionKind kind);
|
bool updateCollision(CollisionKind kind);
|
||||||
|
// Used for setting the second collision kind calculated by object material spaces.
|
||||||
|
bool updateObjectCollision(CollisionKind kind);
|
||||||
|
|
||||||
|
// Calculates the actually-used collision kind based on the tile and object collision kinds.
|
||||||
|
CollisionKind getCollision() const;
|
||||||
|
|
||||||
LiquidStore liquid;
|
LiquidStore liquid;
|
||||||
|
|
||||||
// If set, a plant or object is rooted to the tile and tile damage
|
// If set, a plant or object is rooted to the tile and tile damage
|
||||||
// should be redirected to this position
|
// should be redirected to this position
|
||||||
Maybe<Vec2I> rootSource;
|
Maybe<Vec2I> rootSource;
|
||||||
|
|
||||||
|
// Do not serialize - calculated at runtime
|
||||||
|
CollisionKind objectCollision;
|
||||||
};
|
};
|
||||||
typedef TileSectorArray<ServerTile, WorldSectorSize> ServerTileSectorArray;
|
typedef TileSectorArray<ServerTile, WorldSectorSize> ServerTileSectorArray;
|
||||||
typedef shared_ptr<ServerTileSectorArray> ServerTileSectorArrayPtr;
|
typedef shared_ptr<ServerTileSectorArray> ServerTileSectorArrayPtr;
|
||||||
|
@ -17,7 +17,6 @@ struct MaterialSpace {
|
|||||||
|
|
||||||
Vec2I space;
|
Vec2I space;
|
||||||
MaterialId material;
|
MaterialId material;
|
||||||
Maybe<CollisionKind> prevCollision; //exclude from ==
|
|
||||||
};
|
};
|
||||||
|
|
||||||
DataStream& operator<<(DataStream& ds, MaterialSpace const& materialSpace);
|
DataStream& operator<<(DataStream& ds, MaterialSpace const& materialSpace);
|
||||||
|
Loading…
Reference in New Issue
Block a user