feat(network): synchronize player water sound

This commit is contained in:
2026-07-08 14:37:08 +08:00
parent 69192e5bda
commit 48e19e0af8
10 changed files with 97 additions and 1 deletions

View File

@@ -69,6 +69,8 @@ public:
void receive_remote_player(const PlayerInfoRsp& rsp);
void receive_player_logout(const LogoutRsp& rsp);
void receive_player_water_sound(const PlayerWaterSound& rsp);
void send_player_water_sound(bool underwater, const glm::vec3& pos);
int rendering_distance() const;
void rendering_distance(int rendering_distance);
int get_chunk_task_id() const;

View File

@@ -54,6 +54,7 @@ enum class PacketEnum : uint16_t {
PLAYER_INFO = 2001,
C2S_PLAYER_INFO = 2002,
PLAYER_INFO_RSP = 2003,
PLAYER_WATER_SOUND = 2004,
CHUNK_DATA_REQ = 3001,
CHUNK_DATA_RSP = 3002,
BLOCK_CHANGE_REQ = 3003,
@@ -117,6 +118,9 @@ template <> constexpr uint16_t get_packet_id<Ping>() {
template <> constexpr uint16_t get_packet_id<Pong>() {
return std::to_underlying(PacketEnum::PONG);
}
template <> constexpr uint16_t get_packet_id<PlayerWaterSound>() {
return std::to_underlying(PacketEnum::PLAYER_WATER_SOUND);
}
template <typename T>
requires std::derived_from<T, google::protobuf::Message>

View File

@@ -71,6 +71,7 @@ public:
bool set_block(const glm::ivec3& block_pos, unsigned id);
void sync_player_pos(const C2S_PlayerInfo& rsp);
void sync_player_water_sound(const PlayerWaterSound& rsp);
void handle_player_login(const std::string& player_name,
std::shared_ptr<Session> session);
glm::vec3 get_player_pos(const std::string& uuid) const;

View File

@@ -50,8 +50,11 @@ void Camera::update_move_camera() {
m_under_water = change;
m_player->set_underwater(m_under_water);
auto& audio = m_player->get_world().get_audio();
audio.play_2d("ambient/water/in_and_out_of_water.flac", true);
audio.play_3d("ambient/water/in_and_out_of_water.flac", m_camera_pos,
true);
audio.underwater_change(m_under_water);
m_player->get_world().send_player_water_sound(m_under_water,
m_camera_pos);
}
}

View File

@@ -354,6 +354,33 @@ void ClientWorld::receive_player_logout(const LogoutRsp& rsp) {
}
}
void ClientWorld::receive_player_water_sound(const PlayerWaterSound& rsp) {
if (rsp.uuid() == m_player.get_uuid()) {
return;
}
glm::vec3 pos = {rsp.pos().x(), rsp.pos().y(), rsp.pos().z()};
Logger::info("Client: Receive Player Water Sound");
m_pending_sound.emplace("ambient/water/in_and_out_of_water.flac", pos);
}
void ClientWorld::send_player_water_sound(bool underwater,
const glm::vec3& pos) {
Arena arena;
auto* r = Arena::Create<PlayerWaterSound>(&arena);
r->set_underwater(underwater);
auto* p = r->mutable_pos();
p->set_x(pos.x);
p->set_y(pos.y);
p->set_z(pos.z);
r->set_uuid(m_player.get_uuid());
m_client->send(make_packet(*r));
Logger::info("Client: Send Player Water Sound");
}
void ClientWorld::init(std::string_view player_name,
std::shared_ptr<NetworkClient> client) {
m_player.init(player_name);

View File

@@ -119,6 +119,12 @@ asio::awaitable<void> NetworkClient::read_loop() {
}
}
} break;
case std::to_underlying(PacketEnum::PLAYER_WATER_SOUND): {
auto* rsp = Arena::Create<PlayerWaterSound>(&arena);
if (decode_packet(*rsp, body_data, header)) {
m_world.receive_player_water_sound(*rsp);
}
} break;
}
}
} catch (const asio::system_error& e) {

View File

@@ -597,6 +597,47 @@ void ServerWorld::sync_player_pos(const C2S_PlayerInfo& prsp) {
}
}
void ServerWorld::sync_player_water_sound(const PlayerWaterSound& rsp) {
auto x = rsp.pos().x();
auto y = rsp.pos().y();
auto z = rsp.pos().z();
ChunkPos pos = get_chunk_pos(x, z);
auto uuid = rsp.uuid();
auto underwater = rsp.underwater();
std::vector<std::shared_ptr<Session>> other;
{
std::shared_lock lock(m_player_mutex);
for (auto& [o_uuid, player] : m_players) {
if (o_uuid == uuid) {
continue;
}
if (player.has_player(pos)) {
other.emplace_back(player.get_session());
}
}
}
Arena arena;
auto* r = Arena::Create<PlayerWaterSound>(&arena);
r->set_uuid(uuid);
r->set_underwater(underwater);
auto* p = r->mutable_pos();
p->set_x(x);
p->set_y(y);
p->set_z(z);
for (auto& session : other) {
if (!session) {
continue;
}
session->send(make_packet(*r), 5);
}
}
void ServerWorld::handle_player_login(const std::string& name,
std::shared_ptr<Session> session) {
std::string uuid = generate_uuid();

View File

@@ -92,6 +92,12 @@ asio::awaitable<void> Session::read_loop() {
m_server_world.handle_player_exit(req->uuid());
}
}
if (cmd_id == std::to_underlying(PacketEnum::PLAYER_WATER_SOUND)) {
auto* req = Arena::Create<PlayerWaterSound>(&arena);
if (decode_packet(*req, body_data, header)) {
m_server_world.sync_player_water_sound(*req);
}
}
}
} catch (const asio::system_error& e) {
auto ec = e.code();

View File

@@ -17,4 +17,10 @@ message PlayerInfoRsp {
float yaw = 4;
float pitch = 5;
int32 gait = 6;
}
message PlayerWaterSound {
string uuid = 1;
Vec3 pos = 2;
bool underwater = 3;
}