diff options
| author | untodesu <kirill@untode.su> | 2025-03-22 15:08:17 +0500 |
|---|---|---|
| committer | untodesu <kirill@untode.su> | 2025-03-22 15:08:17 +0500 |
| commit | e34a973f647bc6b7814ad1f3e837689f8478b84a (patch) | |
| tree | 7c8cb1702c16eb68e7acf942d46633a3833bba00 | |
| parent | d8f0fcb101c21b3c4d746d20da6e56e7591006e4 (diff) | |
| download | voxelius-e34a973f647bc6b7814ad1f3e837689f8478b84a.tar.bz2 voxelius-e34a973f647bc6b7814ad1f3e837689f8478b84a.zip | |
A bunch of pre-release fixes
- Updated localization for protocol messages
- Added item registry check into server-side
- Slightly improved how features are stored
| -rw-r--r-- | data/lang/lang.en_US.json | 2 | ||||
| -rw-r--r-- | game/client/receive.cc | 12 | ||||
| -rw-r--r-- | game/client/session.cc | 4 | ||||
| -rw-r--r-- | game/server/game.cc | 3 | ||||
| -rw-r--r-- | game/server/overworld.cc | 67 | ||||
| -rw-r--r-- | game/server/sessions.cc | 10 | ||||
| -rw-r--r-- | game/server/worldgen.cc | 19 | ||||
| -rw-r--r-- | game/server/worldgen.hh | 5 | ||||
| -rw-r--r-- | game/shared/feature.cc | 16 | ||||
| -rw-r--r-- | game/shared/feature.hh | 6 | ||||
| -rw-r--r-- | game/shared/item_registry.cc | 14 | ||||
| -rw-r--r-- | game/shared/item_registry.hh | 5 | ||||
| -rw-r--r-- | game/shared/protocol.cc | 8 | ||||
| -rw-r--r-- | game/shared/protocol.hh | 4 | ||||
| -rw-r--r-- | game/shared/voxel_registry.cc | 2 | ||||
| -rw-r--r-- | game/shared/voxel_registry.hh | 2 |
16 files changed, 127 insertions, 52 deletions
diff --git a/data/lang/lang.en_US.json b/data/lang/lang.en_US.json index d4ebca2..17e05df 100644 --- a/data/lang/lang.en_US.json +++ b/data/lang/lang.en_US.json @@ -141,11 +141,13 @@ "protocol.client_disconnect": "Client disconnect", "protocol.client_shutdown": "Client shutdown", "protocol.entity_id_desync": "Entity ID desync", + "protocol.item_registry_checksum": "Item registry checksum mismatch", "protocol.not_whitelisted": "Not whitelisted", "protocol.outdated_client": "Outdated client", "protocol.outdated_server": "Outdated server", "protocol.password_incorrect": "Incorrect password", "protocol.server_full": "Server is full", + "protocol.server_shutdown": "Server stopped", "protocol.username_taken": "Username is taken", "protocol.voxel_registry_checksum": "Voxel registry checksum mismatch" } diff --git a/game/client/receive.cc b/game/client/receive.cc index 5b053d0..ab1cd62 100644 --- a/game/client/receive.cc +++ b/game/client/receive.cc @@ -12,6 +12,7 @@ #include "client/factory.hh" #include "client/globals.hh" #include "client/gui_screen.hh" +#include "client/message_box.hh" #include "client/session.hh" #include "client/sound.hh" #include "client/window_title.hh" @@ -33,6 +34,17 @@ static bool synchronize_entity_id(Dimension *dimension, entt::entity entity) session::disconnect("protocol.entity_id_desync"); spdlog::critical("receive: entity desync: network {} resolved as client {}", static_cast<std::uint64_t>(entity), static_cast<std::uint64_t>(created)); + + message_box::reset(); + message_box::set_title("disconnected.disconnected"); + message_box::set_subtitle("protocol.entity_id_desync"); + message_box::add_button("disconnected.back", [](void) { + globals::gui_screen = GUI_PLAY_MENU; + window_title::update(); + }); + + globals::gui_screen = GUI_MESSAGE_BOX; + return false; } diff --git a/game/client/session.cc b/game/client/session.cc index 4c4d06b..b5ed12a 100644 --- a/game/client/session.cc +++ b/game/client/session.cc @@ -7,6 +7,7 @@ #include "shared/coord.hh" #include "shared/dimension.hh" #include "shared/head.hh" +#include "shared/item_registry.hh" #include "shared/player.hh" #include "shared/protocol.hh" #include "shared/transform.hh" @@ -275,7 +276,8 @@ void session::send_login_request(void) { protocol::LoginRequest packet; packet.version = protocol::VERSION; - packet.voxel_def_checksum = voxel_registry::checksum(); + packet.voxel_registry_checksum = voxel_registry::calcualte_checksum(); + packet.item_registry_checksum = item_registry::calcualte_checksum(); packet.password_hash = server_password_hash; packet.username = client_game::username.get(); diff --git a/game/server/game.cc b/game/server/game.cc index cc5baf8..c6fc67f 100644 --- a/game/server/game.cc +++ b/game/server/game.cc @@ -28,6 +28,7 @@ #include "server/universe.hh" #include "server/unloader.hh" #include "server/whitelist.hh" +#include "server/worldgen.hh" ConfigUnsigned server_game::view_distance(4U, 4U, 32U); @@ -55,6 +56,8 @@ void server_game::init(void) server_chat::init(); server_recieve::init(); + worldgen::init(); + unloader::init(); universe::init(); } diff --git a/game/server/overworld.cc b/game/server/overworld.cc index 78747fc..608fd01 100644 --- a/game/server/overworld.cc +++ b/game/server/overworld.cc @@ -1,6 +1,8 @@ #include "server/pch.hh" #include "server/overworld.hh" +#include "core/vectors.hh" + #include "shared/coord.hh" #include "shared/game_voxels.hh" #include "shared/voxel_storage.hh" @@ -11,9 +13,12 @@ static void compute_tree_feature(unsigned int height, Feature &feature, voxel_id // Ensure the tree height is too small height = cxpr::max<unsigned int>(height, 4U); + // Put down a single piece of dirt + feature.push_back({ voxel_pos(0, -1, 0), game_voxels::dirt, true }); + // Generate tree stem for(unsigned int i = 0; i < height; ++i) { - feature.push_back({ voxel_pos(0, i, 0), log_voxel }); + feature.push_back({ voxel_pos(0, i, 0), log_voxel, true }); } auto leaves_start = height - 3U; @@ -23,43 +28,43 @@ static void compute_tree_feature(unsigned int height, Feature &feature, voxel_id // Generate the thin 3x3 layer of leaves that // starts from leaves_start and ends at leaves_thin_end for(unsigned int i = leaves_start; i <= leaves_thin_end; ++i) { - feature.push_back({ local_pos(-1, i, -1), leaves_voxel }); - feature.push_back({ local_pos(-1, i, +0), leaves_voxel }); - feature.push_back({ local_pos(-1, i, +1), leaves_voxel }); - feature.push_back({ local_pos(+0, i, -1), leaves_voxel }); - feature.push_back({ local_pos(+0, i, +1), leaves_voxel }); - feature.push_back({ local_pos(+1, i, -1), leaves_voxel }); - feature.push_back({ local_pos(+1, i, +0), leaves_voxel }); - feature.push_back({ local_pos(+1, i, +1), leaves_voxel }); + feature.push_back({ local_pos(-1, i, -1), leaves_voxel, false }); + feature.push_back({ local_pos(-1, i, +0), leaves_voxel, false }); + feature.push_back({ local_pos(-1, i, +1), leaves_voxel, false }); + feature.push_back({ local_pos(+0, i, -1), leaves_voxel, false }); + feature.push_back({ local_pos(+0, i, +1), leaves_voxel, false }); + feature.push_back({ local_pos(+1, i, -1), leaves_voxel, false }); + feature.push_back({ local_pos(+1, i, +0), leaves_voxel, false }); + feature.push_back({ local_pos(+1, i, +1), leaves_voxel, false }); } // Generate the tree cap; a 3x3 patch of leaves // that is slapped right on top of the thin 3x3 layer - feature.push_back({ local_pos(-1, height, +0), leaves_voxel }); - feature.push_back({ local_pos(+0, height, -1), leaves_voxel }); - feature.push_back({ local_pos(+0, height, +0), leaves_voxel }); - feature.push_back({ local_pos(+0, height, +1), leaves_voxel }); - feature.push_back({ local_pos(+1, height, +0), leaves_voxel }); + feature.push_back({ local_pos(-1, height, +0), leaves_voxel, false }); + feature.push_back({ local_pos(+0, height, -1), leaves_voxel, false }); + feature.push_back({ local_pos(+0, height, +0), leaves_voxel, false }); + feature.push_back({ local_pos(+0, height, +1), leaves_voxel, false }); + feature.push_back({ local_pos(+1, height, +0), leaves_voxel, false }); // Generate the thin 5x5 layer of leaves that // starts from leaves_start and ends at leaves_thin_end for(unsigned int i = leaves_start; i <= leaves_thick_end; ++i) { - feature.push_back({ local_pos(-1, i, -2), leaves_voxel }); - feature.push_back({ local_pos(-1, i, +2), leaves_voxel }); - feature.push_back({ local_pos(-2, i, -1), leaves_voxel }); - feature.push_back({ local_pos(-2, i, -2), leaves_voxel }); - feature.push_back({ local_pos(-2, i, +0), leaves_voxel }); - feature.push_back({ local_pos(-2, i, +1), leaves_voxel }); - feature.push_back({ local_pos(-2, i, +2), leaves_voxel }); - feature.push_back({ local_pos(+0, i, -2), leaves_voxel }); - feature.push_back({ local_pos(+0, i, +2), leaves_voxel }); - feature.push_back({ local_pos(+1, i, -2), leaves_voxel }); - feature.push_back({ local_pos(+1, i, +2), leaves_voxel }); - feature.push_back({ local_pos(+2, i, -1), leaves_voxel }); - feature.push_back({ local_pos(+2, i, -2), leaves_voxel }); - feature.push_back({ local_pos(+2, i, +0), leaves_voxel }); - feature.push_back({ local_pos(+2, i, +1), leaves_voxel }); - feature.push_back({ local_pos(+2, i, +2), leaves_voxel }); + feature.push_back({ local_pos(-1, i, -2), leaves_voxel, false }); + feature.push_back({ local_pos(-1, i, +2), leaves_voxel, false }); + feature.push_back({ local_pos(-2, i, -1), leaves_voxel, false }); + feature.push_back({ local_pos(-2, i, -2), leaves_voxel, false }); + feature.push_back({ local_pos(-2, i, +0), leaves_voxel, false }); + feature.push_back({ local_pos(-2, i, +1), leaves_voxel, false }); + feature.push_back({ local_pos(-2, i, +2), leaves_voxel, false }); + feature.push_back({ local_pos(+0, i, -2), leaves_voxel, false }); + feature.push_back({ local_pos(+0, i, +2), leaves_voxel, false }); + feature.push_back({ local_pos(+1, i, -2), leaves_voxel, false }); + feature.push_back({ local_pos(+1, i, +2), leaves_voxel, false }); + feature.push_back({ local_pos(+2, i, -1), leaves_voxel, false }); + feature.push_back({ local_pos(+2, i, -2), leaves_voxel, false }); + feature.push_back({ local_pos(+2, i, +0), leaves_voxel, false }); + feature.push_back({ local_pos(+2, i, +1), leaves_voxel, false }); + feature.push_back({ local_pos(+2, i, +2), leaves_voxel, false }); } } @@ -216,7 +221,7 @@ const Overworld_Metadata &Overworld::get_or_create_metadata(const chunk_pos_xz & auto is_unique = true; for(const auto &check_lpos : metadata.trees) { - if(check_lpos == lpos) { + if(cxvectors::distance2(check_lpos, lpos) <= 9) { is_unique = false; break; } diff --git a/game/server/sessions.cc b/game/server/sessions.cc index f2e643d..58f12d4 100644 --- a/game/server/sessions.cc +++ b/game/server/sessions.cc @@ -11,6 +11,7 @@ #include "shared/dimension.hh" #include "shared/factory.hh" #include "shared/head.hh" +#include "shared/item_registry.hh" #include "shared/player.hh" #include "shared/protocol.hh" #include "shared/transform.hh" @@ -56,13 +57,20 @@ static void on_login_request_packet(const protocol::LoginRequest &packet) // FIXME: calculate voxel registry checksum ahead of time // instead of figuring it out every time a new player connects - if(packet.voxel_def_checksum != voxel_registry::checksum()) { + if(packet.voxel_registry_checksum != voxel_registry::calcualte_checksum()) { protocol::Disconnect response; response.reason = "protocol.voxel_registry_checksum"; protocol::send(packet.peer, protocol::encode(response)); return; } + if(packet.item_registry_checksum != item_registry::calcualte_checksum()) { + protocol::Disconnect response; + response.reason = "protocol.item_registry_checksum"; + protocol::send(packet.peer, protocol::encode(response)); + return; + } + // Don't assign new usernames and just kick the player if // an another client using the same username is already connected // and playing; since we have a whitelist, adding "(1)" isn't feasible anymore diff --git a/game/server/worldgen.cc b/game/server/worldgen.cc index 83fddbb..4fc37c7 100644 --- a/game/server/worldgen.cc +++ b/game/server/worldgen.cc @@ -1,13 +1,19 @@ #include "server/pch.hh" #include "server/worldgen.hh" +#include "core/config.hh" + #include "shared/chunk.hh" #include "shared/dimension.hh" #include "shared/protocol.hh" #include "shared/threading.hh" +#include "server/globals.hh" +#include "server/inhabited.hh" #include "server/sessions.hh" +static ConfigBoolean aggressive_caching(false); + static emhash8::HashMap<Dimension *, emhash8::HashMap<chunk_pos, std::unordered_set<Session *>>> active_tasks; class WorldgenTask final : public Task { @@ -60,6 +66,14 @@ void WorldgenTask::finalize(void) auto chunk = m_dimension->create_chunk(m_cpos); chunk->set_voxels(m_voxels); + if(aggressive_caching.get_value()) { + // Marking the chunk with InhabitedComponent makes + // it so that it is saved regardles of whether it was + // modified by players or not. This isn't particularly + // good for server-side disk usage but it might improve performance + m_dimension->chunks.emplace<InhabitedComponent>(chunk->get_entity()); + } + protocol::ChunkVoxels response; response.voxels = m_voxels; response.chunk = m_cpos; @@ -84,6 +98,11 @@ void WorldgenTask::finalize(void) } } +void worldgen::init(void) +{ + globals::server_config.add_value("worldgen.aggressive_caching", aggressive_caching); +} + bool worldgen::is_generating(Dimension *dimension, const chunk_pos &cpos) { auto dim_tasks = active_tasks.find(dimension); diff --git a/game/server/worldgen.hh b/game/server/worldgen.hh index 3153071..7fb08b9 100644 --- a/game/server/worldgen.hh +++ b/game/server/worldgen.hh @@ -9,6 +9,11 @@ class Session; namespace worldgen { +void init(void); +} // namespace worldgen + +namespace worldgen +{ bool is_generating(Dimension *dimension, const chunk_pos &cpos); void request_chunk(Session *session, const chunk_pos &cpos); } // namespace worldgen diff --git a/game/shared/feature.cc b/game/shared/feature.cc index 6f884b2..845bb40 100644 --- a/game/shared/feature.cc +++ b/game/shared/feature.cc @@ -6,10 +6,10 @@ #include "shared/dimension.hh" #include "shared/voxel_storage.hh" -void Feature::place(const voxel_pos &vpos, Dimension *dimension, bool overwrite) const +void Feature::place(const voxel_pos &vpos, Dimension *dimension) const { - for(const auto &it : (*this)) { - auto it_vpos = vpos + it.first; + for(const auto [rpos, voxel, overwrite] : (*this)) { + auto it_vpos = vpos + rpos; auto it_cpos = coord::to_chunk(it_vpos); if(auto chunk = dimension->create_chunk(it_cpos)) { @@ -23,15 +23,15 @@ void Feature::place(const voxel_pos &vpos, Dimension *dimension, bool overwrite) continue; } - chunk->set_voxel(it.second, it_index); + chunk->set_voxel(voxel, it_index); } } } -void Feature::place(const voxel_pos &vpos, const chunk_pos &cpos, VoxelStorage &voxels, bool overwrite) const +void Feature::place(const voxel_pos &vpos, const chunk_pos &cpos, VoxelStorage &voxels) const { - for(const auto &it : (*this)) { - auto it_vpos = vpos + it.first; + for(const auto [rpos, voxel, overwrite] : (*this)) { + auto it_vpos = vpos + rpos; auto it_cpos = coord::to_chunk(it_vpos); if(it_cpos == cpos) { @@ -45,7 +45,7 @@ void Feature::place(const voxel_pos &vpos, const chunk_pos &cpos, VoxelStorage & continue; } - voxels[it_index] = it.second; + voxels[it_index] = voxel; } } } diff --git a/game/shared/feature.hh b/game/shared/feature.hh index f5fe73b..b5cb262 100644 --- a/game/shared/feature.hh +++ b/game/shared/feature.hh @@ -7,14 +7,14 @@ class Dimension; class VoxelStorage; -class Feature final : public std::vector<std::pair<voxel_pos, voxel_id>> { +class Feature final : public std::vector<std::tuple<voxel_pos, voxel_id, bool>> { public: explicit Feature(void) = default; virtual ~Feature(void) = default; public: - void place(const voxel_pos &vpos, Dimension *dimension, bool overwrite = false) const; - void place(const voxel_pos &vpos, const chunk_pos &cpos, VoxelStorage &voxels, bool overwrite = false) const; + void place(const voxel_pos &vpos, Dimension *dimension) const; + void place(const voxel_pos &vpos, const chunk_pos &cpos, VoxelStorage &voxels) const; }; #endif /* SHARED_FEATURE_HH */ diff --git a/game/shared/item_registry.cc b/game/shared/item_registry.cc index 02164bd..23dffdc 100644 --- a/game/shared/item_registry.cc +++ b/game/shared/item_registry.cc @@ -1,6 +1,8 @@ #include "shared/pch.hh" #include "shared/item_registry.hh" +#include "core/crc64.hh" + #include "shared/voxel_registry.hh" std::unordered_map<std::string, ItemInfoBuilder> item_registry::builders = {}; @@ -78,3 +80,15 @@ void item_registry::purge(void) item_registry::names.clear(); item_registry::items.clear(); } + +std::uint64_t item_registry::calcualte_checksum(void) +{ + std::uint64_t result = 0; + + for(const auto &info : item_registry::items) { + result = crc64::get(info->name, result); + result += static_cast<std::uint64_t>(info->place_voxel); + } + + return result; +} diff --git a/game/shared/item_registry.hh b/game/shared/item_registry.hh index 7160b0b..83b6053 100644 --- a/game/shared/item_registry.hh +++ b/game/shared/item_registry.hh @@ -54,4 +54,9 @@ namespace item_registry void purge(void); } // namespace item_registry +namespace item_registry +{ +std::uint64_t calcualte_checksum(void); +} // namespace item_registry + #endif /* SHARED_ITEM_REGISTRY_HH */ diff --git a/game/shared/protocol.cc b/game/shared/protocol.cc index e2c79b5..3b32701 100644 --- a/game/shared/protocol.cc +++ b/game/shared/protocol.cc @@ -39,8 +39,8 @@ ENetPacket *protocol::encode(const protocol::LoginRequest &packet, enet_uint32 f write_buffer.reset(); write_buffer.write_UI16(protocol::LoginRequest::ID); write_buffer.write_UI32(packet.version); - write_buffer.write_UI64(packet.voxel_def_checksum); - write_buffer.write_UI64(packet.item_def_checksum); + write_buffer.write_UI64(packet.voxel_registry_checksum); + write_buffer.write_UI64(packet.item_registry_checksum); write_buffer.write_UI64(packet.password_hash); write_buffer.write_string(packet.username.substr(0, protocol::MAX_USERNAME)); return write_buffer.to_packet(flags); @@ -280,8 +280,8 @@ void protocol::decode(entt::dispatcher &dispatcher, const ENetPacket *packet, EN case protocol::LoginRequest::ID: login_request.peer = peer; login_request.version = read_buffer.read_UI32(); - login_request.voxel_def_checksum = read_buffer.read_UI64(); - login_request.item_def_checksum = read_buffer.read_UI64(); + login_request.voxel_registry_checksum = read_buffer.read_UI64(); + login_request.item_registry_checksum = read_buffer.read_UI64(); login_request.password_hash = read_buffer.read_UI64(); login_request.username = read_buffer.read_string(); dispatcher.trigger(login_request); diff --git a/game/shared/protocol.hh b/game/shared/protocol.hh index 0b8b0f1..727ab1f 100644 --- a/game/shared/protocol.hh +++ b/game/shared/protocol.hh @@ -118,8 +118,8 @@ struct protocol::StatusResponse final : public protocol::Base<0x0001> { struct protocol::LoginRequest final : public protocol::Base<0x0002> { std::uint32_t version; - std::uint64_t voxel_def_checksum; - std::uint64_t item_def_checksum; + std::uint64_t voxel_registry_checksum; + std::uint64_t item_registry_checksum; std::uint64_t password_hash; std::string username; }; diff --git a/game/shared/voxel_registry.cc b/game/shared/voxel_registry.cc index dea7179..ce6ee7f 100644 --- a/game/shared/voxel_registry.cc +++ b/game/shared/voxel_registry.cc @@ -169,7 +169,7 @@ void voxel_registry::purge(void) voxel_registry::voxels.clear(); } -std::uint64_t voxel_registry::checksum(void) +std::uint64_t voxel_registry::calcualte_checksum(void) { std::uint64_t result = 0; diff --git a/game/shared/voxel_registry.hh b/game/shared/voxel_registry.hh index 722cec1..b12bc68 100644 --- a/game/shared/voxel_registry.hh +++ b/game/shared/voxel_registry.hh @@ -138,7 +138,7 @@ void purge(void); namespace voxel_registry { -std::uint64_t checksum(void); +std::uint64_t calcualte_checksum(void); } // namespace voxel_registry #endif /* SHARED_VOXEL_REGISTRY_HH */ |
