Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix crash caused by the entity vector being invalidated #227

Merged
merged 2 commits into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cubic-server/Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ void Client::_onStatusRequest()
return;
}

json["version"]["name"] = MC_VERSION;
json["version"]["name"] = MC_VERSION_BRANDING;
json["version"]["protocol"] = MC_PROTOCOL;
json["players"]["max"] = conf["max-players"].as<int32_t>();
{
Expand Down
70 changes: 48 additions & 22 deletions cubic-server/Dimension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "Server.hpp"
#include "World.hpp"
#include "entities/Entity.hpp"
#include "entities/EntityType.hpp"
#include "logging/logging.hpp"
#include "math/Vector3.hpp"
#include "protocol/ClientPackets.hpp"
Expand All @@ -24,9 +25,11 @@ Dimension::Dimension(std::shared_ptr<World> world, world_storage::DimensionType

void Dimension::tick()
{
std::lock_guard _(_entitiesMutex);
for (auto ent : _entities) {
ent->tick();
{
std::lock_guard _(_entitiesMutex);
for (auto ent : _entities) {
ent->tick();
}
}
uint32_t rts = CONFIG["randomtickspeed"].as<uint32_t>();
if (rts != 0) {
Expand All @@ -37,6 +40,16 @@ void Dimension::tick()
chunk.processRandomTick(rts);
}
}
{
std::unique_lock a(_entitiesMutex, std::defer_lock);
std::unique_lock b(_newEntitiesMutex, std::defer_lock);
std::lock(a, b);

if (_newEntities.size() != 0) {
_entities.insert(_entities.end(), _newEntities.begin(), _newEntities.end());
_newEntities.clear();
}
}
}

void Dimension::stop()
Expand Down Expand Up @@ -115,8 +128,8 @@ void Dimension::removePlayer(int32_t entity_id)

void Dimension::addEntity(std::shared_ptr<Entity> entity)
{
std::lock_guard _(_entitiesMutex);
_entities.emplace_back(entity);
std::lock_guard _(_newEntitiesMutex);
_newEntities.emplace_back(entity);
}

void Dimension::addPlayer(std::shared_ptr<Player> entity)
Expand Down Expand Up @@ -220,24 +233,37 @@ const world_storage::ChunkColumn &Dimension::getChunk(const Position2D &pos) con
void Dimension::spawnPlayer(Player &current)
{
auto current_id = current.getId();
std::lock_guard _(_playersMutex);
for (auto player : _players) {
LDEBUG("player is: {}", player->getUsername());
LDEBUG("current is: {}", current.getUsername());
// if (current->getPos().distance(player->getPos()) <= 12) {
if (player->getId() != current_id) {
player->sendSpawnPlayer(
{current_id, current.getUuid(), current.getPosition().x, current.getPosition().y, current.getPosition().z, current.getRotation().x, current.getRotation().z}
);
LDEBUG("send spawn player to {}", player->getUsername());
current.sendSpawnPlayer(
{player->getId(), player->getUuid(), player->getPosition().x, player->getPosition().y, player->getPosition().z, player->getRotation().x, player->getRotation().z}
);
LDEBUG("send spawn player to {}", current.getUsername());
//}
{

std::lock_guard _(_playersMutex);
for (auto player : _players) {
LDEBUG("player is: {}", player->getUsername());
LDEBUG("current is: {}", current.getUsername());
// if (current->getPos().distance(player->getPos()) <= 12) {
if (player->getId() != current_id) {
player->sendSpawnPlayer(
{current_id, current.getUuid(), current.getPosition().x, current.getPosition().y, current.getPosition().z, current.getRotation().x, current.getRotation().z}
);
LDEBUG("send spawn player to {}", player->getUsername());
current.sendSpawnPlayer(
{player->getId(), player->getUuid(), player->getPosition().x, player->getPosition().y, player->getPosition().z, player->getRotation().x,
player->getRotation().z}
);
LDEBUG("send spawn player to {}", current.getUsername());
//}
}
player->sendEntityMetadata(current);
current.sendEntityMetadata(*player);
}
}
{
std::lock_guard _(_entitiesMutex);
for (auto ent : _entities) {
if (ent->getType() == EntityType::Player)
continue;
current.sendSpawnEntity(*ent);
current.sendEntityMetadata(*ent);
}
player->sendEntityMetadata(current);
current.sendEntityMetadata(*player);
}
}

Expand Down
2 changes: 2 additions & 0 deletions cubic-server/Dimension.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,13 @@ class Dimension : public std::enable_shared_from_this<Dimension> {
public:
mutable std::recursive_mutex _playersMutex;
mutable std::recursive_mutex _entitiesMutex;
mutable std::recursive_mutex _newEntitiesMutex;
mutable std::mutex _loadingChunksMutex;

protected:
std::counting_semaphore<SEMAPHORE_MAX> _dimensionLock;
std::vector<std::shared_ptr<Entity>> _entities;
std::vector<std::shared_ptr<Entity>> _newEntities;
std::vector<std::shared_ptr<Player>> _players;
std::shared_ptr<World> _world;
std::mutex _processingMutex;
Expand Down
23 changes: 23 additions & 0 deletions cubic-server/Player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,29 @@ void Player::sendSpawnEntity(const protocol::SpawnEntity &data)
N_LDEBUG("Sent a Spawn Entity packet");
}

void Player::sendSpawnEntity(const Entity &data)
{
GET_CLIENT();
auto pck = protocol::createSpawnEntity({
data.getId(), // Entity ID
data.getUuid(), // Entity UUID
data.getType(), // Entity Type
data.getPosition().x, // Entity Position X
data.getPosition().y, // Entity Position Y
data.getPosition().z, // Entity Position Z
0, // Entity Pitch
0, // Entity Yaw
0, // Entity Head Yaw
0, // Entity data
0, // Entity Velocity X
0, // Entity Velocity Y
0 // Entity Velocity Z
});
client->doWrite(std::move(pck));

N_LDEBUG("Sent a Spawn Entity packet");
}

void Player::sendSpawnPlayer(const protocol::SpawnPlayer &data)
{
GET_CLIENT();
Expand Down
1 change: 1 addition & 0 deletions cubic-server/Player.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ class Player : public LivingEntity {
void sendPlayerInfoUpdate(const protocol::PlayerInfoUpdate &data);
void sendPlayerInfoRemove(const protocol::PlayerInfoRemove &data);
void sendSpawnEntity(const protocol::SpawnEntity &data);
void sendSpawnEntity(const Entity &data);
void sendSpawnPlayer(const protocol::SpawnPlayer &data);
void sendEntityVelocity(const protocol::EntityVelocity &data);
void sendHealth(void);
Expand Down
1 change: 1 addition & 0 deletions cubic-server/Server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include "registry/MasterRegistry.hpp"

constexpr char MC_VERSION[] = "1.19.3";
constexpr char MC_VERSION_BRANDING[] = "CubicServer 1.19.3";
constexpr uint16_t MC_PROTOCOL = 761;
constexpr uint16_t MS_PER_TICK = 50;

Expand Down
1 change: 1 addition & 0 deletions cubic-server/allCommands.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@
#include "command_parser/commands/Scoreboard.hpp"
#include "command_parser/commands/Seed.hpp"
#include "command_parser/commands/Stop.hpp"
#include "command_parser/commands/Teleport.hpp"
#include "command_parser/commands/Time.hpp"
2 changes: 1 addition & 1 deletion cubic-server/entities/Chicken.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ void Chicken::layEgg()
auto time = utility::PseudoRandomGenerator::getInstance()->generateNumber(6000, 12000);
LDEBUG("Chicken will drop egg in {} ticks", time);
_layEgg.setTickRate(time);
_dim->makeEntity<Item>(protocol::Slot {true, ITEM_CONVERTER.fromItemToProtocolId("minecraft:egg"), 1})->dropItem({_pos.x, _pos.y + 1, _pos.z});
_dim->makeEntity<Item>(protocol::Slot {true, ITEM_CONVERTER.fromItemToProtocolId("minecraft:egg"), 1})->dropItem({_pos.x, _pos.y + 1, _pos.z}, false);
LDEBUG("Chicken dropped egg at x: {}, y: {}, z: {}", _pos.x, _pos.y + 1, _pos.z);
}

Expand Down