mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-09 02:07:04 +08:00
Compare commits
2 Commits
8faf4c9a81
...
720f9fe0c1
| Author | SHA1 | Date | |
|---|---|---|---|
| 720f9fe0c1 | |||
| 85db85a737 |
@@ -6,6 +6,7 @@
|
|||||||
#include "Cubed/gameplay/game_mode.hpp"
|
#include "Cubed/gameplay/game_mode.hpp"
|
||||||
#include "Cubed/input.hpp"
|
#include "Cubed/input.hpp"
|
||||||
|
|
||||||
|
#include <absl/container/flat_hash_set.h>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <shared_mutex>
|
#include <shared_mutex>
|
||||||
@@ -14,8 +15,14 @@ enum class Gait { WALK = 0, RUN };
|
|||||||
class ClientWorld;
|
class ClientWorld;
|
||||||
class ClientPlayer {
|
class ClientPlayer {
|
||||||
public:
|
public:
|
||||||
|
using ChunkPosSet = absl::flat_hash_set<ChunkPos, ChunkPos::Hash>;
|
||||||
ClientPlayer(ClientWorld& world);
|
ClientPlayer(ClientWorld& world);
|
||||||
~ClientPlayer();
|
~ClientPlayer();
|
||||||
|
|
||||||
|
void update_chunk_set(const ChunkPosSet& set);
|
||||||
|
const ChunkPosSet& get_chunk_pos_set() const;
|
||||||
|
ChunkPosSet& get_chunk_pos_set();
|
||||||
|
|
||||||
AABB get_aabb(const glm::vec3& pos) const;
|
AABB get_aabb(const glm::vec3& pos) const;
|
||||||
const glm::vec3& get_front() const;
|
const glm::vec3& get_front() const;
|
||||||
const Gait& get_gait() const;
|
const Gait& get_gait() const;
|
||||||
@@ -101,7 +108,8 @@ private:
|
|||||||
ClientWorld& m_world;
|
ClientWorld& m_world;
|
||||||
|
|
||||||
mutable std::shared_mutex m_player_pos_mutex;
|
mutable std::shared_mutex m_player_pos_mutex;
|
||||||
|
mutable std::shared_mutex m_chunk_pos_mutex;
|
||||||
|
ChunkPosSet m_player_chunk_pos_set;
|
||||||
bool ray_cast(const glm::vec3& start, const glm::vec3& dir,
|
bool ray_cast(const glm::vec3& start, const glm::vec3& dir,
|
||||||
glm::ivec3& block_pos, glm::vec3& normal,
|
glm::ivec3& block_pos, glm::vec3& normal,
|
||||||
float distance = 4.0f);
|
float distance = 4.0f);
|
||||||
|
|||||||
@@ -7,7 +7,10 @@
|
|||||||
#include "Cubed/gameplay/network_client.hpp"
|
#include "Cubed/gameplay/network_client.hpp"
|
||||||
#include "Cubed/tools/thread_pool.hpp"
|
#include "Cubed/tools/thread_pool.hpp"
|
||||||
|
|
||||||
|
#include <absl/container/flat_hash_set.h>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include <tbb/concurrent_hash_map.h>
|
||||||
|
#include <tbb/concurrent_queue.h>
|
||||||
#include <tbb/concurrent_unordered_map.h>
|
#include <tbb/concurrent_unordered_map.h>
|
||||||
namespace Cubed {
|
namespace Cubed {
|
||||||
|
|
||||||
@@ -64,10 +67,10 @@ public:
|
|||||||
const std::vector<ChunkRenderSnapshot>& render_snapshots() const;
|
const std::vector<ChunkRenderSnapshot>& render_snapshots() const;
|
||||||
const std::vector<RemotePlayerRenderData>& render_player_data() const;
|
const std::vector<RemotePlayerRenderData>& render_player_data() const;
|
||||||
glm::vec3 sunlight_dir() const;
|
glm::vec3 sunlight_dir() const;
|
||||||
void receive_chunk(ChunkDataRsp data);
|
void receive_chunk(std::vector<uint8_t> data, PacketHeader header);
|
||||||
void request_exit();
|
void request_exit();
|
||||||
bool is_receive_exit();
|
bool is_receive_exit();
|
||||||
|
int chunk_size() const;
|
||||||
template <typename Fn>
|
template <typename Fn>
|
||||||
void register_timer(std::string_view id, TickType threshold, Fn&& f) {
|
void register_timer(std::string_view id, TickType threshold, Fn&& f) {
|
||||||
m_timers.emplace(std::piecewise_construct,
|
m_timers.emplace(std::piecewise_construct,
|
||||||
@@ -78,12 +81,14 @@ public:
|
|||||||
private:
|
private:
|
||||||
enum class ChunkLoadStyle { RANDOM, CENTER };
|
enum class ChunkLoadStyle { RANDOM, CENTER };
|
||||||
using ChunkHashMap =
|
using ChunkHashMap =
|
||||||
tbb::concurrent_unordered_map<ChunkPos, ClientChunk, ChunkPos::Hash>;
|
tbb::concurrent_hash_map<ChunkPos, std::shared_ptr<ClientChunk>,
|
||||||
using ChunkPosSet = std::unordered_set<ChunkPos, ChunkPos::Hash>;
|
ChunkPos::TBBHash>;
|
||||||
|
using ChunkPosSet = absl::flat_hash_set<ChunkPos, ChunkPos::Hash>;
|
||||||
using ChunkPosVector = std::vector<ChunkPos>;
|
using ChunkPosVector = std::vector<ChunkPos>;
|
||||||
using OtherPlayerHashMap =
|
using OtherPlayerHashMap =
|
||||||
std::unordered_map<std::string, RemotePlayerInfo>;
|
std::unordered_map<std::string, RemotePlayerInfo>;
|
||||||
|
using chunk_acc = ChunkHashMap::accessor;
|
||||||
|
using chunk_cacc = ChunkHashMap::const_accessor;
|
||||||
static constexpr int WORLD_EXIT_TIMEOUT = 200;
|
static constexpr int WORLD_EXIT_TIMEOUT = 200;
|
||||||
|
|
||||||
ClientPlayer m_player;
|
ClientPlayer m_player;
|
||||||
@@ -92,13 +97,11 @@ private:
|
|||||||
std::vector<glm::vec4> m_planes;
|
std::vector<glm::vec4> m_planes;
|
||||||
std::jthread m_client_thread;
|
std::jthread m_client_thread;
|
||||||
|
|
||||||
mutable std::shared_mutex m_chunks_mutex;
|
|
||||||
std::mutex m_delete_vbo_mutex;
|
std::mutex m_delete_vbo_mutex;
|
||||||
std::mutex m_delete_vao_mutex;
|
std::mutex m_delete_vao_mutex;
|
||||||
std::mutex m_pending_upload_queue_mutex;
|
|
||||||
std::mutex m_other_players_mutex;
|
std::mutex m_other_players_mutex;
|
||||||
|
|
||||||
std::deque<ClientChunk> m_pending_upload_queue;
|
tbb::concurrent_queue<std::unique_ptr<ClientChunk>> m_pending_upload_queue;
|
||||||
|
|
||||||
std::vector<GLuint> m_pending_delete_vbo;
|
std::vector<GLuint> m_pending_delete_vbo;
|
||||||
std::vector<GLuint> m_pending_delete_vao;
|
std::vector<GLuint> m_pending_delete_vao;
|
||||||
@@ -127,5 +130,7 @@ private:
|
|||||||
void report_player_pos();
|
void report_player_pos();
|
||||||
|
|
||||||
void set_block(const glm::ivec3& pos, unsigned id);
|
void set_block(const glm::ivec3& pos, unsigned id);
|
||||||
|
|
||||||
|
void update_chunk(const ChunkPosSet& old, const ChunkPosSet& now);
|
||||||
};
|
};
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
|
|||||||
@@ -576,6 +576,7 @@ void DevPanel::show_client_world_table_bar() {
|
|||||||
m_player->set_player_pos({0.0f, 255.0f, 0.0f});
|
m_player->set_player_pos({0.0f, 255.0f, 0.0f});
|
||||||
}
|
}
|
||||||
ImGui::Text("Chunk Task Id %d", m_app.client_world().get_chunk_task_id());
|
ImGui::Text("Chunk Task Id %d", m_app.client_world().get_chunk_task_id());
|
||||||
|
ImGui::Text("Client World Chunk %d", m_app.client_world().chunk_size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DevPanel::show_player_tab_item() {
|
void DevPanel::show_player_tab_item() {
|
||||||
|
|||||||
@@ -542,6 +542,22 @@ void ClientPlayer::update_scroll(double yoffset) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClientPlayer::update_chunk_set(const ChunkPosSet& set) {
|
||||||
|
std::lock_guard lock(m_chunk_pos_mutex);
|
||||||
|
m_player_chunk_pos_set.clear();
|
||||||
|
m_player_chunk_pos_set.insert(set.begin(), set.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
const ClientPlayer::ChunkPosSet& ClientPlayer::get_chunk_pos_set() const {
|
||||||
|
std::shared_lock lock(m_chunk_pos_mutex);
|
||||||
|
return m_player_chunk_pos_set;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientPlayer::ChunkPosSet& ClientPlayer::get_chunk_pos_set() {
|
||||||
|
std::lock_guard lock(m_chunk_pos_mutex);
|
||||||
|
return m_player_chunk_pos_set;
|
||||||
|
}
|
||||||
|
|
||||||
float& ClientPlayer::max_walk_speed() { return m_max_walk_speed; }
|
float& ClientPlayer::max_walk_speed() { return m_max_walk_speed; }
|
||||||
float& ClientPlayer::max_run_speed() { return m_max_run_speed; }
|
float& ClientPlayer::max_run_speed() { return m_max_run_speed; }
|
||||||
float& ClientPlayer::max_speed() { return m_max_speed; }
|
float& ClientPlayer::max_speed() { return m_max_speed; }
|
||||||
|
|||||||
@@ -23,10 +23,9 @@ ClientWorld::ClientWorld() : m_player(*this) {}
|
|||||||
ClientWorld::~ClientWorld() {
|
ClientWorld::~ClientWorld() {
|
||||||
stop_client_thread();
|
stop_client_thread();
|
||||||
stop_thread_pool();
|
stop_thread_pool();
|
||||||
{
|
|
||||||
std::lock_guard lock(m_chunks_mutex);
|
|
||||||
m_chunks.clear();
|
m_chunks.clear();
|
||||||
}
|
|
||||||
{
|
{
|
||||||
std::lock_guard lk(m_delete_vbo_mutex);
|
std::lock_guard lk(m_delete_vbo_mutex);
|
||||||
for (auto x : m_pending_delete_vbo) {
|
for (auto x : m_pending_delete_vbo) {
|
||||||
@@ -53,14 +52,13 @@ ClientPlayer& ClientWorld::get_player() { return m_player; }
|
|||||||
|
|
||||||
int ClientWorld::get_block(const glm::ivec3& block_pos) const {
|
int ClientWorld::get_block(const glm::ivec3& block_pos) const {
|
||||||
auto [chunk_x, chunk_z] = get_chunk_pos(block_pos.x, block_pos.z);
|
auto [chunk_x, chunk_z] = get_chunk_pos(block_pos.x, block_pos.z);
|
||||||
std::shared_lock lk(m_chunks_mutex);
|
chunk_cacc cacc;
|
||||||
auto it = m_chunks.find(ChunkPos{chunk_x, chunk_z});
|
|
||||||
|
|
||||||
if (it == m_chunks.end()) {
|
if (!m_chunks.find(cacc, ChunkPos{chunk_x, chunk_z})) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& chunk_blocks = it->second.get_chunk_blocks();
|
const auto& chunk_blocks = cacc->second->get_chunk_blocks();
|
||||||
auto [x, y, z] = ClientChunk::world_to_block(block_pos, {chunk_x, chunk_z});
|
auto [x, y, z] = ClientChunk::world_to_block(block_pos, {chunk_x, chunk_z});
|
||||||
if (x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_SIZE_Y ||
|
if (x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_SIZE_Y ||
|
||||||
z >= CHUNK_SIZE) {
|
z >= CHUNK_SIZE) {
|
||||||
@@ -70,13 +68,12 @@ int ClientWorld::get_block(const glm::ivec3& block_pos) const {
|
|||||||
}
|
}
|
||||||
bool ClientWorld::is_solid(const glm::ivec3& block_pos) const {
|
bool ClientWorld::is_solid(const glm::ivec3& block_pos) const {
|
||||||
auto [chunk_x, chunk_z] = get_chunk_pos(block_pos.x, block_pos.z);
|
auto [chunk_x, chunk_z] = get_chunk_pos(block_pos.x, block_pos.z);
|
||||||
std::shared_lock lk(m_chunks_mutex);
|
chunk_cacc cacc;
|
||||||
auto it = m_chunks.find(ChunkPos{chunk_x, chunk_z});
|
|
||||||
|
|
||||||
if (it == m_chunks.end()) {
|
if (!m_chunks.find(cacc, ChunkPos{chunk_x, chunk_z})) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto& chunk_blocks = it->second.get_chunk_blocks();
|
const auto& chunk_blocks = cacc->second->get_chunk_blocks();
|
||||||
auto [x, y, z] = ClientChunk::world_to_block(block_pos, {chunk_x, chunk_z});
|
auto [x, y, z] = ClientChunk::world_to_block(block_pos, {chunk_x, chunk_z});
|
||||||
if (x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_SIZE_Y ||
|
if (x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_SIZE_Y ||
|
||||||
z >= CHUNK_SIZE) {
|
z >= CHUNK_SIZE) {
|
||||||
@@ -91,13 +88,12 @@ bool ClientWorld::is_solid(const glm::ivec3& block_pos) const {
|
|||||||
}
|
}
|
||||||
bool ClientWorld::can_pass_block(const glm::ivec3& block_pos) const {
|
bool ClientWorld::can_pass_block(const glm::ivec3& block_pos) const {
|
||||||
auto [chunk_x, chunk_z] = get_chunk_pos(block_pos.x, block_pos.z);
|
auto [chunk_x, chunk_z] = get_chunk_pos(block_pos.x, block_pos.z);
|
||||||
std::shared_lock lk(m_chunks_mutex);
|
chunk_cacc cacc;
|
||||||
auto it = m_chunks.find(ChunkPos{chunk_x, chunk_z});
|
|
||||||
|
|
||||||
if (it == m_chunks.end()) {
|
if (!m_chunks.find(cacc, ChunkPos{chunk_x, chunk_z})) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const auto& chunk_blocks = it->second.get_chunk_blocks();
|
const auto& chunk_blocks = cacc->second->get_chunk_blocks();
|
||||||
auto [x, y, z] = ClientChunk::world_to_block(block_pos, {chunk_x, chunk_z});
|
auto [x, y, z] = ClientChunk::world_to_block(block_pos, {chunk_x, chunk_z});
|
||||||
if (x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_SIZE_Y ||
|
if (x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_SIZE_Y ||
|
||||||
z >= CHUNK_SIZE) {
|
z >= CHUNK_SIZE) {
|
||||||
@@ -111,31 +107,31 @@ void ClientWorld::rebuild_world() {
|
|||||||
if (m_is_rebuilding.exchange(true)) {
|
if (m_is_rebuilding.exchange(true)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stop_client_thread();
|
||||||
stop_thread_pool();
|
stop_thread_pool();
|
||||||
{
|
|
||||||
std::lock_guard lk(m_chunks_mutex);
|
|
||||||
m_chunks.clear();
|
m_chunks.clear();
|
||||||
}
|
|
||||||
{
|
|
||||||
std::lock_guard lock(m_pending_upload_queue_mutex);
|
|
||||||
m_pending_upload_queue.clear();
|
m_pending_upload_queue.clear();
|
||||||
}
|
|
||||||
start_thread_pool();
|
start_thread_pool();
|
||||||
|
start_client_thread(m_player.get_uuid());
|
||||||
request_chunk();
|
request_chunk();
|
||||||
m_is_rebuilding = false;
|
m_is_rebuilding = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockType ClientWorld::get_block_tpye(const glm::ivec3& block_pos) const {
|
BlockType ClientWorld::get_block_tpye(const glm::ivec3& block_pos) const {
|
||||||
auto [chunk_x, chunk_z] = get_chunk_pos(block_pos.x, block_pos.z);
|
auto [chunk_x, chunk_z] = get_chunk_pos(block_pos.x, block_pos.z);
|
||||||
std::shared_lock lk(m_chunks_mutex);
|
chunk_cacc cacc;
|
||||||
auto it = m_chunks.find(ChunkPos{chunk_x, chunk_z});
|
;
|
||||||
|
|
||||||
if (it == m_chunks.end()) {
|
if (!m_chunks.find(cacc, ChunkPos{chunk_x, chunk_z})) {
|
||||||
// Logger::error("Can't Find Block {} {} {}", block_pos.x, block_pos.y,
|
// Logger::error("Can't Find Block {} {} {}", block_pos.x, block_pos.y,
|
||||||
// block_pos.z);
|
// block_pos.z);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
const auto& chunk_blocks = it->second.get_chunk_blocks();
|
const auto& chunk_blocks = cacc->second->get_chunk_blocks();
|
||||||
auto [x, y, z] = ClientChunk::world_to_block(block_pos, {chunk_x, chunk_z});
|
auto [x, y, z] = ClientChunk::world_to_block(block_pos, {chunk_x, chunk_z});
|
||||||
if (x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_SIZE_Y ||
|
if (x < 0 || y < 0 || z < 0 || x >= CHUNK_SIZE || y >= WORLD_SIZE_Y ||
|
||||||
z >= CHUNK_SIZE) {
|
z >= CHUNK_SIZE) {
|
||||||
@@ -152,10 +148,10 @@ void ClientWorld::set_block(const glm::ivec3& block_pos, unsigned id) {
|
|||||||
world_z = block_pos.z;
|
world_z = block_pos.z;
|
||||||
|
|
||||||
auto [chunk_x, chunk_z] = get_chunk_pos(world_x, world_z);
|
auto [chunk_x, chunk_z] = get_chunk_pos(world_x, world_z);
|
||||||
std::lock_guard lk(m_chunks_mutex);
|
{
|
||||||
auto it = m_chunks.find(ChunkPos{chunk_x, chunk_z});
|
chunk_acc acc;
|
||||||
|
|
||||||
if (it == m_chunks.end()) {
|
if (!m_chunks.find(acc, ChunkPos{chunk_x, chunk_z})) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,7 +162,8 @@ void ClientWorld::set_block(const glm::ivec3& block_pos, unsigned id) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
it->second.set_chunk_block(ClientChunk::index(x, y, z), id);
|
acc->second->set_chunk_block(ClientChunk::index(x, y, z), id);
|
||||||
|
}
|
||||||
|
|
||||||
static const glm::ivec3 NEIGHBOR_DIRS[] = {
|
static const glm::ivec3 NEIGHBOR_DIRS[] = {
|
||||||
{1, 0, 0}, {-1, 0, 0}, {0, 0, -1}, {0, 0, 1}};
|
{1, 0, 0}, {-1, 0, 0}, {0, 0, -1}, {0, 0, 1}};
|
||||||
@@ -175,9 +172,11 @@ void ClientWorld::set_block(const glm::ivec3& block_pos, unsigned id) {
|
|||||||
glm::ivec3 neighbor = block_pos + dir;
|
glm::ivec3 neighbor = block_pos + dir;
|
||||||
|
|
||||||
auto [cx, cz] = get_chunk_pos(neighbor.x, neighbor.z);
|
auto [cx, cz] = get_chunk_pos(neighbor.x, neighbor.z);
|
||||||
auto it = m_chunks.find({cx, cz});
|
{
|
||||||
if (it != m_chunks.end()) {
|
chunk_acc acc;
|
||||||
it->second.mark_dirty();
|
if (m_chunks.find(acc, {cx, cz})) {
|
||||||
|
acc->second->mark_dirty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -251,7 +250,6 @@ void ClientWorld::receive_player_logout(const LogoutRsp& rsp) {
|
|||||||
|
|
||||||
void ClientWorld::init(std::string_view player_name,
|
void ClientWorld::init(std::string_view player_name,
|
||||||
std::shared_ptr<NetworkClient> client) {
|
std::shared_ptr<NetworkClient> client) {
|
||||||
m_chunks.reserve(MAX_DISTANCE * MAX_DISTANCE * 4);
|
|
||||||
m_player.init(player_name);
|
m_player.init(player_name);
|
||||||
m_client = client;
|
m_client = client;
|
||||||
// timer
|
// timer
|
||||||
@@ -361,6 +359,26 @@ void ClientWorld::report_player_pos() {
|
|||||||
m_client->send(make_packet(*pos));
|
m_client->send(make_packet(*pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClientWorld::update_chunk(const ChunkPosSet& old, const ChunkPosSet& now) {
|
||||||
|
|
||||||
|
// Elements in the old set that are not contained in now are not needed by
|
||||||
|
// the current player.
|
||||||
|
|
||||||
|
for (auto& pos : old) {
|
||||||
|
if (!now.contains(pos)) {
|
||||||
|
|
||||||
|
chunk_acc acc;
|
||||||
|
if (!m_chunks.find(acc, pos)) {
|
||||||
|
Logger::warn("Update Ref Count Error, can't Find old pos "
|
||||||
|
"in m_chunks");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_chunks.erase(acc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ClientWorld::request_chunk() {
|
void ClientWorld::request_chunk() {
|
||||||
if (m_requesting_chunk.exchange(true)) {
|
if (m_requesting_chunk.exchange(true)) {
|
||||||
Logger::warn("It is requesting new chunk!");
|
Logger::warn("It is requesting new chunk!");
|
||||||
@@ -386,24 +404,20 @@ void ClientWorld::request_chunk() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ChunkPosSet old = std::move(m_player.get_chunk_pos_set());
|
||||||
|
m_player.update_chunk_set(required_chunks);
|
||||||
|
|
||||||
ChunkPosVector need_send_pos;
|
ChunkPosVector need_send_pos;
|
||||||
{
|
|
||||||
std::lock_guard lk(m_chunks_mutex);
|
|
||||||
for (auto it = m_chunks.begin(); it != m_chunks.end();) {
|
|
||||||
if (required_chunks.find(it->first) == required_chunks.end()) {
|
|
||||||
it = m_chunks.unsafe_erase(it);
|
|
||||||
} else {
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto pos : required_chunks) {
|
for (auto pos : required_chunks) {
|
||||||
auto it = m_chunks.find(pos);
|
chunk_cacc cacc;
|
||||||
if (it == m_chunks.end()) {
|
if (!m_chunks.find(cacc, pos)) {
|
||||||
need_send_pos.emplace_back(pos);
|
need_send_pos.emplace_back(pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
update_chunk(old, required_chunks);
|
||||||
|
|
||||||
if (need_send_pos.empty()) {
|
if (need_send_pos.empty()) {
|
||||||
m_requesting_chunk = false;
|
m_requesting_chunk = false;
|
||||||
return;
|
return;
|
||||||
@@ -416,9 +430,8 @@ void ClientWorld::request_chunk() {
|
|||||||
case CENTER: {
|
case CENTER: {
|
||||||
|
|
||||||
glm::vec3 player_pos = m_player.get_player_pos();
|
glm::vec3 player_pos = m_player.get_player_pos();
|
||||||
auto dist2 = [player_pos](ChunkPos chunk_pos) {
|
ChunkPos player_chunk_pos = get_chunk_pos(player_pos.x, player_pos.z);
|
||||||
ChunkPos player_chunk_pos =
|
auto dist2 = [player_chunk_pos](ChunkPos chunk_pos) {
|
||||||
get_chunk_pos(player_pos.x, player_pos.z);
|
|
||||||
float dx = player_chunk_pos.x - chunk_pos.x;
|
float dx = player_chunk_pos.x - chunk_pos.x;
|
||||||
float dz = player_chunk_pos.z - chunk_pos.z;
|
float dz = player_chunk_pos.z - chunk_pos.z;
|
||||||
return dx * dx + dz * dz;
|
return dx * dx + dz * dz;
|
||||||
@@ -446,36 +459,48 @@ void ClientWorld::request_chunk() {
|
|||||||
m_requesting_chunk = false;
|
m_requesting_chunk = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientWorld::receive_chunk(ChunkDataRsp data) {
|
void ClientWorld::receive_chunk(std::vector<uint8_t> raw_data,
|
||||||
if (data.task_id() < m_chunk_task_id) {
|
PacketHeader header) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
std::lock_guard lock(m_chunks_mutex);
|
|
||||||
ChunkPos pos{data.pos().x(), data.pos().z()};
|
|
||||||
if (m_chunks.find(pos) != m_chunks.end()) {
|
|
||||||
Logger::warn("Chunk {} {} has already in client world", pos.x,
|
|
||||||
pos.z);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// vertex data will genrator in client thread pool instead of net thread;
|
// vertex data will genrator in client thread pool instead of net thread;
|
||||||
auto pool = m_thread_pool.load();
|
auto pool = m_thread_pool.load();
|
||||||
if (!pool) {
|
if (!pool) {
|
||||||
Logger::error("Client Thread Pool is nullptr");
|
Logger::error("Client Thread Pool is nullptr");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pool->enqueue([this, data = std::move(data)]() {
|
pool->enqueue(
|
||||||
ClientChunk chunk{*this};
|
[this, raw_data = std::move(raw_data), header = std::move(header)]() {
|
||||||
chunk.receive_chunk(data);
|
Arena arena;
|
||||||
{
|
auto* data = Arena::Create<ChunkDataRsp>(&arena);
|
||||||
std::lock_guard lock(m_pending_upload_queue_mutex);
|
if (!decode_packet(*data, raw_data, header)) {
|
||||||
m_pending_upload_queue.emplace_back(std::move(chunk));
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data->task_id() < m_chunk_task_id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
chunk_cacc cacc;
|
||||||
|
ChunkPos pos{data->pos().x(), data->pos().z()};
|
||||||
|
if (m_chunks.find(cacc, pos)) {
|
||||||
|
Logger::warn("Chunk {} {} has already in client world",
|
||||||
|
pos.x, pos.z);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<ClientChunk> chunk =
|
||||||
|
std::make_unique<ClientChunk>(*this);
|
||||||
|
chunk->receive_chunk(*data);
|
||||||
|
|
||||||
|
m_pending_upload_queue.emplace(std::move(chunk));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
bool ClientWorld::is_receive_exit() { return m_receive_exit; }
|
bool ClientWorld::is_receive_exit() { return m_receive_exit; }
|
||||||
|
|
||||||
|
int ClientWorld::chunk_size() const { return m_chunks.size(); }
|
||||||
|
|
||||||
void ClientWorld::request_exit() {
|
void ClientWorld::request_exit() {
|
||||||
if (m_receive_exit) {
|
if (m_receive_exit) {
|
||||||
return;
|
return;
|
||||||
@@ -512,51 +537,60 @@ void ClientWorld::update(float delta_time) {
|
|||||||
}
|
}
|
||||||
m_pending_delete_vao.clear();
|
m_pending_delete_vao.clear();
|
||||||
}
|
}
|
||||||
std::vector<ClientChunk> new_chunks;
|
std::vector<std::unique_ptr<ClientChunk>> new_chunks;
|
||||||
{
|
{
|
||||||
std::lock_guard lock(m_pending_upload_queue_mutex);
|
std::unique_ptr<ClientChunk> chunk;
|
||||||
for (auto& c : m_pending_upload_queue) {
|
while (m_pending_upload_queue.try_pop(chunk)) {
|
||||||
// Logger::info("{} {}", c.get_chunk_pos().x, c.get_chunk_pos().z);
|
new_chunks.emplace_back(std::move(chunk));
|
||||||
new_chunks.emplace_back(std::move(c));
|
|
||||||
}
|
}
|
||||||
m_pending_upload_queue.clear();
|
|
||||||
}
|
}
|
||||||
for (auto& c : new_chunks) {
|
for (auto& c : new_chunks) {
|
||||||
c.upload_to_gpu();
|
c->upload_to_gpu();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
std::lock_guard lock(m_chunks_mutex);
|
|
||||||
for (auto& c : new_chunks) {
|
for (auto& c : new_chunks) {
|
||||||
m_chunks.emplace(c.get_chunk_pos(), std::move(c));
|
m_chunks.emplace(c->get_chunk_pos(), std::move(c));
|
||||||
}
|
}
|
||||||
m_render_snapshots.clear();
|
m_render_snapshots.clear();
|
||||||
for (auto& [pos, chunk] : m_chunks) {
|
auto chunk_pos_set = m_player.get_chunk_pos_set();
|
||||||
if (chunk.is_dirty()) {
|
for (auto& pos : chunk_pos_set) {
|
||||||
|
std::shared_ptr<ClientChunk> chunk;
|
||||||
|
{
|
||||||
|
chunk_acc acc;
|
||||||
|
if (m_chunks.find(acc, pos)) {
|
||||||
|
chunk = acc->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!chunk) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (chunk->is_dirty()) {
|
||||||
// the curial fator influence
|
// the curial fator influence
|
||||||
OptionalBlockVectorArray neighbor_block;
|
OptionalBlockVectorArray neighbor_block;
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
auto it = m_chunks.find(pos + CHUNK_DIR[i]);
|
chunk_cacc cacc;
|
||||||
if (it != m_chunks.end()) {
|
if (m_chunks.find(cacc, pos + CHUNK_DIR[i])) {
|
||||||
neighbor_block[i] = (it->second.get_chunk_blocks());
|
neighbor_block[i] = (cacc->second->get_chunk_blocks());
|
||||||
} else {
|
} else {
|
||||||
neighbor_block[i] = std::nullopt;
|
neighbor_block[i] = std::nullopt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
chunk.gen_vertex_data(neighbor_block);
|
chunk->gen_vertex_data(neighbor_block);
|
||||||
chunk.upload_to_gpu();
|
chunk->upload_to_gpu();
|
||||||
}
|
}
|
||||||
if (!chunk.is_dirty()) {
|
if (!chunk->is_dirty()) {
|
||||||
if (chunk.is_need_upload()) {
|
if (chunk->is_need_upload()) {
|
||||||
chunk.upload_to_gpu();
|
chunk->upload_to_gpu();
|
||||||
}
|
}
|
||||||
m_render_snapshots.push_back(
|
m_render_snapshots.push_back(
|
||||||
{chunk.get_normal_vao(), chunk.get_normal_vertices_sum(),
|
{chunk->get_normal_vao(), chunk->get_normal_vertices_sum(),
|
||||||
chunk.get_cross_vao(), chunk.get_cross_vertices_sum(),
|
chunk->get_cross_vao(), chunk->get_cross_vertices_sum(),
|
||||||
chunk.get_normal_discard_vao(),
|
chunk->get_normal_discard_vao(),
|
||||||
chunk.get_normal_discard_vertices_sum(),
|
chunk->get_normal_discard_vertices_sum(),
|
||||||
chunk.get_normal_blend_vao(),
|
chunk->get_normal_blend_vao(),
|
||||||
chunk.get_normal_blend_vertices_sum(),
|
chunk->get_normal_blend_vertices_sum(),
|
||||||
chunk.get_water_vao(), chunk.get_water_vertices_sum(),
|
chunk->get_water_vao(), chunk->get_water_vertices_sum(),
|
||||||
glm::vec3(static_cast<float>(pos.x * CHUNK_SIZE) +
|
glm::vec3(static_cast<float>(pos.x * CHUNK_SIZE) +
|
||||||
static_cast<float>(CHUNK_SIZE / 2),
|
static_cast<float>(CHUNK_SIZE / 2),
|
||||||
static_cast<float>(WORLD_SIZE_Y / 2),
|
static_cast<float>(WORLD_SIZE_Y / 2),
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ asio::awaitable<void> NetworkClient::read_loop() {
|
|||||||
|
|
||||||
throw std::runtime_error("invalid packet length");
|
throw std::runtime_error("invalid packet length");
|
||||||
}
|
}
|
||||||
|
// maybe move, don't use it after switch!
|
||||||
std::vector<uint8_t> body_data(header.compressed_size);
|
std::vector<uint8_t> body_data(header.compressed_size);
|
||||||
if (header.compressed_size > 0) {
|
if (header.compressed_size > 0) {
|
||||||
co_await asio::async_read(m_socket, asio::buffer(body_data),
|
co_await asio::async_read(m_socket, asio::buffer(body_data),
|
||||||
@@ -80,12 +81,9 @@ asio::awaitable<void> NetworkClient::read_loop() {
|
|||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case std::to_underlying(PacketEnum::CHUNK_DATA_RSP): {
|
case std::to_underlying(PacketEnum::CHUNK_DATA_RSP): {
|
||||||
ChunkDataRsp rsp;
|
|
||||||
// Logger::info("Client: Receive Chunk Data rsp, size {}mb",
|
// Logger::info("Client: Receive Chunk Data rsp, size {}mb",
|
||||||
// body_data.size() / 1024.0f / 1024);
|
// body_data.size() / 1024.0f / 1024);
|
||||||
if (decode_packet(rsp, body_data, header)) {
|
m_world.receive_chunk(std::move(body_data), header);
|
||||||
m_world.receive_chunk(std::move(rsp));
|
|
||||||
}
|
|
||||||
} break;
|
} break;
|
||||||
case std::to_underlying(PacketEnum::BLOCK_CHANGE_RSP): {
|
case std::to_underlying(PacketEnum::BLOCK_CHANGE_RSP): {
|
||||||
auto* rsp = Arena::Create<BlockChangeRsp>(&arena);
|
auto* rsp = Arena::Create<BlockChangeRsp>(&arena);
|
||||||
|
|||||||
@@ -1,5 +1,14 @@
|
|||||||
#include "Cubed/app.hpp"
|
#include "Cubed/app.hpp"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
__declspec(dllexport) unsigned long NvOptimusEnablement = 1;
|
||||||
|
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
|
|
||||||
static_assert(sizeof(int) == sizeof(int32_t));
|
static_assert(sizeof(int) == sizeof(int32_t));
|
||||||
|
|||||||
Reference in New Issue
Block a user